mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
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://",
|
||||
"https://",
|
||||
"file://",
|
||||
"cgi://"
|
||||
"cgi://",
|
||||
">http://",
|
||||
">https://",
|
||||
};
|
||||
|
||||
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;
|
||||
if (next)
|
||||
next->mount_next = m;
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(mount_protocols); n++)
|
||||
if (!strncmp(origin, 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"))
|
||||
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"))
|
||||
return "image/png";
|
||||
|
||||
|
@ -203,6 +209,9 @@ static const char * get_mimetype(const char *file)
|
|||
if (!strcmp(&file[n - 4], ".css"))
|
||||
return "text/css";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".ttf"))
|
||||
return "application/x-font-ttf";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -233,9 +242,7 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
|||
int
|
||||
lws_http_action(struct lws *wsi)
|
||||
{
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
#endif
|
||||
enum http_connection_type connection_type;
|
||||
enum http_version request_version;
|
||||
char content_length_str[32];
|
||||
|
@ -395,7 +402,6 @@ lws_http_action(struct lws *wsi)
|
|||
|
||||
hm = wsi->vhost->mount_list;
|
||||
while (hm) {
|
||||
lwsl_err("a %p\n", hm);
|
||||
if (uri_len >= hm->mountpoint_len &&
|
||||
!strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len)) {
|
||||
if (hm->mountpoint_len > best) {
|
||||
|
@ -405,23 +411,75 @@ lws_http_action(struct lws *wsi)
|
|||
}
|
||||
hm = hm->mount_next;
|
||||
}
|
||||
lwsl_err("x\n");
|
||||
if (hit) {
|
||||
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;
|
||||
|
||||
if (!s)
|
||||
s = "index.html";
|
||||
lwsl_err("b\n");
|
||||
n = lws_http_serve(wsi, s, hit->origin);
|
||||
} else {
|
||||
lwsl_err("c\n");
|
||||
|
||||
} else
|
||||
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
|
||||
wsi->user_space, uri_ptr, uri_len);
|
||||
}
|
||||
|
||||
if (n) {
|
||||
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
||||
|
||||
|
@ -895,22 +953,11 @@ lws_http_transaction_completed(struct lws *wsi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static struct lws *
|
||||
lws_adopt_socket_vhost(struct lws_vhost *vh, 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) {
|
||||
compatible_close(accept_fd);
|
||||
|
@ -962,6 +1009,25 @@ fail:
|
|||
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
|
||||
* @context: lws context
|
||||
|
@ -1273,7 +1339,7 @@ try_pollout:
|
|||
break;
|
||||
}
|
||||
|
||||
if (!lws_adopt_socket(context, accept_fd))
|
||||
if (!lws_adopt_socket_vhost(wsi->vhost, accept_fd))
|
||||
/* already closed cleanly as necessary */
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg)
|
|||
if (servername) {
|
||||
vhost = lws_select_vhost(context, port, servername);
|
||||
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);
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ static const char * const paths_vhosts[] = {
|
|||
"vhosts[].mounts[].default",
|
||||
"vhosts[].ws-protocols[].*.*",
|
||||
"vhosts[].ws-protocols[].*",
|
||||
"vhosts[].ws-protocols[]"
|
||||
"vhosts[].ws-protocols[]",
|
||||
};
|
||||
|
||||
enum lejp_vhost_paths {
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
<tr>
|
||||
<td valign=middle align=center>
|
||||
<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:
|
||||
<div id=brow>...</div></section>
|
||||
</td>
|
||||
|
@ -96,7 +96,7 @@
|
|||
</table>
|
||||
</td></tr>
|
||||
<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.
|
||||
</td></tr>
|
||||
<tr><td colspan=2>
|
||||
|
|
Loading…
Add table
Reference in a new issue