lwsws redirect and correct vhost selection before accept
Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
37098ae2a2
commit
d459a6fadc
5 changed files with 100 additions and 31 deletions
|
@ -44,7 +44,9 @@ static const char * const mount_protocols[] = {
|
||||||
"http://",
|
"http://",
|
||||||
"https://",
|
"https://",
|
||||||
"file://",
|
"file://",
|
||||||
"cgi://"
|
"cgi://",
|
||||||
|
">http://",
|
||||||
|
">https://",
|
||||||
};
|
};
|
||||||
|
|
||||||
LWS_VISIBLE LWS_EXTERN int
|
LWS_VISIBLE LWS_EXTERN int
|
||||||
|
@ -70,6 +72,7 @@ lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
|
||||||
m->mount_next = NULL;
|
m->mount_next = NULL;
|
||||||
if (next)
|
if (next)
|
||||||
next->mount_next = m;
|
next->mount_next = m;
|
||||||
|
|
||||||
for (n = 0; n < ARRAY_SIZE(mount_protocols); n++)
|
for (n = 0; n < ARRAY_SIZE(mount_protocols); n++)
|
||||||
if (!strncmp(origin, mount_protocols[n],
|
if (!strncmp(origin, mount_protocols[n],
|
||||||
strlen(mount_protocols[n]))) {
|
strlen(mount_protocols[n]))) {
|
||||||
|
|
118
lib/server.c
118
lib/server.c
|
@ -191,6 +191,12 @@ static const char * get_mimetype(const char *file)
|
||||||
if (!strcmp(&file[n - 4], ".ico"))
|
if (!strcmp(&file[n - 4], ".ico"))
|
||||||
return "image/x-icon";
|
return "image/x-icon";
|
||||||
|
|
||||||
|
if (!strcmp(&file[n - 4], ".gif"))
|
||||||
|
return "image/gif";
|
||||||
|
|
||||||
|
if (!strcmp(&file[n - 3], ".js"))
|
||||||
|
return "text/javascript";
|
||||||
|
|
||||||
if (!strcmp(&file[n - 4], ".png"))
|
if (!strcmp(&file[n - 4], ".png"))
|
||||||
return "image/png";
|
return "image/png";
|
||||||
|
|
||||||
|
@ -203,6 +209,9 @@ static const char * get_mimetype(const char *file)
|
||||||
if (!strcmp(&file[n - 4], ".css"))
|
if (!strcmp(&file[n - 4], ".css"))
|
||||||
return "text/css";
|
return "text/css";
|
||||||
|
|
||||||
|
if (!strcmp(&file[n - 4], ".ttf"))
|
||||||
|
return "application/x-font-ttf";
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,9 +242,7 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
||||||
int
|
int
|
||||||
lws_http_action(struct lws *wsi)
|
lws_http_action(struct lws *wsi)
|
||||||
{
|
{
|
||||||
#ifdef LWS_OPENSSL_SUPPORT
|
|
||||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||||
#endif
|
|
||||||
enum http_connection_type connection_type;
|
enum http_connection_type connection_type;
|
||||||
enum http_version request_version;
|
enum http_version request_version;
|
||||||
char content_length_str[32];
|
char content_length_str[32];
|
||||||
|
@ -395,7 +402,6 @@ lws_http_action(struct lws *wsi)
|
||||||
|
|
||||||
hm = wsi->vhost->mount_list;
|
hm = wsi->vhost->mount_list;
|
||||||
while (hm) {
|
while (hm) {
|
||||||
lwsl_err("a %p\n", hm);
|
|
||||||
if (uri_len >= hm->mountpoint_len &&
|
if (uri_len >= hm->mountpoint_len &&
|
||||||
!strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len)) {
|
!strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len)) {
|
||||||
if (hm->mountpoint_len > best) {
|
if (hm->mountpoint_len > best) {
|
||||||
|
@ -405,23 +411,75 @@ lws_http_action(struct lws *wsi)
|
||||||
}
|
}
|
||||||
hm = hm->mount_next;
|
hm = hm->mount_next;
|
||||||
}
|
}
|
||||||
lwsl_err("x\n");
|
|
||||||
if (hit) {
|
if (hit) {
|
||||||
char *s = uri_ptr + hit->mountpoint_len;
|
char *s = uri_ptr + hit->mountpoint_len;
|
||||||
|
|
||||||
if (s[0] == '\0')
|
lwsl_err("*** hit %d %d %s\n", hit->mountpoint_len, hit->origin_protocol , hit->origin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we have a mountpoint like https://xxx.com/yyy
|
||||||
|
* there is an implied / at the end for our purposes since
|
||||||
|
* we can only mount on a "directory".
|
||||||
|
*
|
||||||
|
* But if we just go with that, the browser cannot understand
|
||||||
|
* that he is actually looking down one "directory level", so
|
||||||
|
* even though we give him /yyy/abc.html he acts like the
|
||||||
|
* current directory level is /. So relative urls like "x.png"
|
||||||
|
* wrongly look outside the mountpoint.
|
||||||
|
*
|
||||||
|
* Therefore if we didn't come in on a url with an explicit
|
||||||
|
* / at the end, we must redirect to add it so the browser
|
||||||
|
* understands he is one "directory level" down.
|
||||||
|
*/
|
||||||
|
if (hit->mountpoint_len > 1 || (hit->origin_protocol & 4))
|
||||||
|
if (*s != '/' || (hit->origin_protocol & 4)) {
|
||||||
|
unsigned char *start = pt->serv_buf + LWS_PRE,
|
||||||
|
*p = start, *end = p + 512;
|
||||||
|
static const char *oprot[] = {
|
||||||
|
"http://", "https://"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
|
||||||
|
goto bail_nuke_ah;
|
||||||
|
if (lws_add_http_header_status(wsi, 301, &p, end))
|
||||||
|
goto bail_nuke_ah;
|
||||||
|
|
||||||
|
lwsl_err("**** %s", hit->origin);
|
||||||
|
|
||||||
|
/* > at start indicates deal with by redirect */
|
||||||
|
if (hit->origin_protocol & 4)
|
||||||
|
n = snprintf((char *)end, 256, "%s%s",
|
||||||
|
oprot[hit->origin_protocol & 1],
|
||||||
|
hit->origin);
|
||||||
|
else
|
||||||
|
n = snprintf((char *)end, 256,
|
||||||
|
"https://%s/%s/",
|
||||||
|
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
|
||||||
|
uri_ptr);
|
||||||
|
if (lws_add_http_header_by_token(wsi,
|
||||||
|
WSI_TOKEN_HTTP_LOCATION,
|
||||||
|
end, n, &p, end))
|
||||||
|
goto bail_nuke_ah;
|
||||||
|
if (lws_finalize_http_header(wsi, &p, end))
|
||||||
|
goto bail_nuke_ah;
|
||||||
|
n = lws_write(wsi, start, p - start,
|
||||||
|
LWS_WRITE_HTTP_HEADERS);
|
||||||
|
if ((int)n < 0)
|
||||||
|
goto bail_nuke_ah;
|
||||||
|
|
||||||
|
return lws_http_transaction_completed(wsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s[0] == '\0' || (s[0] == '/' && s[1] == '\0'))
|
||||||
s = (char *)hit->def;
|
s = (char *)hit->def;
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
s = "index.html";
|
s = "index.html";
|
||||||
lwsl_err("b\n");
|
|
||||||
n = lws_http_serve(wsi, s, hit->origin);
|
n = lws_http_serve(wsi, s, hit->origin);
|
||||||
} else {
|
} else
|
||||||
lwsl_err("c\n");
|
|
||||||
|
|
||||||
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
|
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
|
||||||
wsi->user_space, uri_ptr, uri_len);
|
wsi->user_space, uri_ptr, uri_len);
|
||||||
}
|
|
||||||
if (n) {
|
if (n) {
|
||||||
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
||||||
|
|
||||||
|
@ -895,22 +953,11 @@ lws_http_transaction_completed(struct lws *wsi)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static struct lws *
|
||||||
* lws_adopt_socket() - adopt foreign socket as if listen socket accepted it
|
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
|
||||||
* @context: lws context
|
|
||||||
* @accept_fd: fd of already-accepted socket to adopt
|
|
||||||
*
|
|
||||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
|
||||||
* returns NULL, having cleaned up any new wsi pieces.
|
|
||||||
*
|
|
||||||
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
|
|
||||||
* to ws or just serve http.
|
|
||||||
*/
|
|
||||||
|
|
||||||
LWS_VISIBLE struct lws *
|
|
||||||
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
|
|
||||||
{
|
{
|
||||||
struct lws *new_wsi = lws_create_new_server_wsi(context->vhost_list);
|
struct lws_context *context = vh->context;
|
||||||
|
struct lws *new_wsi = lws_create_new_server_wsi(vh);
|
||||||
|
|
||||||
if (!new_wsi) {
|
if (!new_wsi) {
|
||||||
compatible_close(accept_fd);
|
compatible_close(accept_fd);
|
||||||
|
@ -962,6 +1009,25 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lws_adopt_socket() - adopt foreign socket as if listen socket accepted it
|
||||||
|
* @context: lws context
|
||||||
|
* @accept_fd: fd of already-accepted socket to adopt
|
||||||
|
*
|
||||||
|
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||||
|
* returns NULL, having cleaned up any new wsi pieces.
|
||||||
|
*
|
||||||
|
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
|
||||||
|
* to ws or just serve http.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LWS_VISIBLE struct lws *
|
||||||
|
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
|
||||||
|
{
|
||||||
|
return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
|
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
|
||||||
* @context: lws context
|
* @context: lws context
|
||||||
|
@ -1273,7 +1339,7 @@ try_pollout:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lws_adopt_socket(context, accept_fd))
|
if (!lws_adopt_socket_vhost(wsi->vhost, accept_fd))
|
||||||
/* already closed cleanly as necessary */
|
/* already closed cleanly as necessary */
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg)
|
||||||
if (servername) {
|
if (servername) {
|
||||||
vhost = lws_select_vhost(context, port, servername);
|
vhost = lws_select_vhost(context, port, servername);
|
||||||
if (vhost) {
|
if (vhost) {
|
||||||
lwsl_info("SNI: Found: %s\n", servername);
|
lwsl_notice("SNI: Found: %s (port %d)\n", servername, port);
|
||||||
SSL_set_SSL_CTX(ssl, vhost->ssl_ctx);
|
SSL_set_SSL_CTX(ssl, vhost->ssl_ctx);
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ static const char * const paths_vhosts[] = {
|
||||||
"vhosts[].mounts[].default",
|
"vhosts[].mounts[].default",
|
||||||
"vhosts[].ws-protocols[].*.*",
|
"vhosts[].ws-protocols[].*.*",
|
||||||
"vhosts[].ws-protocols[].*",
|
"vhosts[].ws-protocols[].*",
|
||||||
"vhosts[].ws-protocols[]"
|
"vhosts[].ws-protocols[]",
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lejp_vhost_paths {
|
enum lejp_vhost_paths {
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td valign=middle align=center>
|
<td valign=middle align=center>
|
||||||
<a href="https://libwebsockets.org">
|
<a href="https://libwebsockets.org">
|
||||||
<img src="/libwebsockets.org-logo.png"></a></td><td>
|
<img src="libwebsockets.org-logo.png"></a></td><td>
|
||||||
<section class="browser">Detected Browser:
|
<section class="browser">Detected Browser:
|
||||||
<div id=brow>...</div></section>
|
<div id=brow>...</div></section>
|
||||||
</td>
|
</td>
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
</table>
|
</table>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td colspan=2 align=center>
|
<tr><td colspan=2 align=center>
|
||||||
Click <a href="/leaf.jpg" target="_blank">Here</a> to
|
Click <a href="leaf.jpg" target="_blank">Here</a> to
|
||||||
have the test server send a big picture by http.
|
have the test server send a big picture by http.
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td colspan=2>
|
<tr><td colspan=2>
|
||||||
|
|
Loading…
Add table
Reference in a new issue