mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
http server: favour redirect over ws upgrade
This commit is contained in:
parent
db15061e87
commit
bc0ab4b656
2 changed files with 118 additions and 64 deletions
|
@ -773,11 +773,13 @@ lws_client_interpret_server_handshake(struct lws *wsi)
|
|||
wsi->http.conn_type = HTTP_CONNECTION_KEEP_ALIVE;
|
||||
if (!wsi->client_mux_substream) {
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
|
||||
/*
|
||||
if (wsi->do_ws && !p) {
|
||||
lwsl_info("no URI\n");
|
||||
cce = "HS: URI missing";
|
||||
goto bail3;
|
||||
}
|
||||
*/
|
||||
if (!p) {
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
|
||||
wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
|
||||
|
|
|
@ -1251,14 +1251,99 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static const char * const oprot[] = {
|
||||
"http://", "https://"
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
lws_http_redirect_hit(struct lws_context_per_thread *pt, struct lws *wsi,
|
||||
const struct lws_http_mount *hit, char *uri_ptr,
|
||||
int uri_len, int *h)
|
||||
{
|
||||
char *s;
|
||||
int n;
|
||||
|
||||
*h = 0;
|
||||
s = uri_ptr + hit->mountpoint_len;
|
||||
|
||||
/*
|
||||
* 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 == LWSMPRO_REDIR_HTTP ||
|
||||
hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
|
||||
(*s != '/' ||
|
||||
(hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
|
||||
hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
|
||||
(hit->origin_protocol != LWSMPRO_CGI &&
|
||||
hit->origin_protocol != LWSMPRO_CALLBACK)) {
|
||||
unsigned char *start = pt->serv_buf + LWS_PRE, *p = start,
|
||||
*end = p + wsi->context->pt_serv_buf_size -
|
||||
LWS_PRE - 512;
|
||||
|
||||
*h = 1;
|
||||
|
||||
lwsl_info("Doing 301 '%s' org %s\n", s, hit->origin);
|
||||
|
||||
/* > at start indicates deal with by redirect */
|
||||
if (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
|
||||
hit->origin_protocol == LWSMPRO_REDIR_HTTPS)
|
||||
n = lws_snprintf((char *)end, 256, "%s%s",
|
||||
oprot[hit->origin_protocol & 1],
|
||||
hit->origin);
|
||||
else {
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
|
||||
if (!lws_hdr_total_length(wsi,
|
||||
WSI_TOKEN_HTTP_COLON_AUTHORITY))
|
||||
goto bail_nuke_ah;
|
||||
n = lws_snprintf((char *)end, 256,
|
||||
"%s%s%s/", oprot[!!lws_is_ssl(wsi)],
|
||||
lws_hdr_simple_ptr(wsi,
|
||||
WSI_TOKEN_HTTP_COLON_AUTHORITY),
|
||||
uri_ptr);
|
||||
} else
|
||||
n = lws_snprintf((char *)end, 256,
|
||||
"%s%s%s/", oprot[!!lws_is_ssl(wsi)],
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
|
||||
uri_ptr);
|
||||
}
|
||||
|
||||
lws_clean_url((char *)end);
|
||||
n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
|
||||
end, n, &p, end);
|
||||
if ((int)n < 0)
|
||||
goto bail_nuke_ah;
|
||||
|
||||
return lws_http_transaction_completed(wsi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bail_nuke_ah:
|
||||
lws_header_table_detach(wsi, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
lws_http_action(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
int uri_len = 0, meth, m, http_version_len, ha;
|
||||
const struct lws_http_mount *hit = NULL;
|
||||
enum http_version request_version;
|
||||
struct lws_process_html_args args;
|
||||
|
@ -1266,9 +1351,7 @@ lws_http_action(struct lws *wsi)
|
|||
char content_length_str[32];
|
||||
char http_version_str[12];
|
||||
char *uri_ptr = NULL, *s;
|
||||
int uri_len = 0, meth, m;
|
||||
char http_conn_str[25];
|
||||
int http_version_len;
|
||||
unsigned int n;
|
||||
|
||||
meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
|
||||
|
@ -1427,67 +1510,9 @@ lws_http_action(struct lws *wsi)
|
|||
}
|
||||
|
||||
s = uri_ptr + hit->mountpoint_len;
|
||||
|
||||
/*
|
||||
* 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 == LWSMPRO_REDIR_HTTP ||
|
||||
hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
|
||||
(*s != '/' ||
|
||||
(hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
|
||||
hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
|
||||
(hit->origin_protocol != LWSMPRO_CGI &&
|
||||
hit->origin_protocol != LWSMPRO_CALLBACK)) {
|
||||
unsigned char *start = pt->serv_buf + LWS_PRE, *p = start,
|
||||
*end = p + wsi->context->pt_serv_buf_size -
|
||||
LWS_PRE - 512;
|
||||
|
||||
lwsl_info("Doing 301 '%s' org %s\n", s, hit->origin);
|
||||
|
||||
/* > at start indicates deal with by redirect */
|
||||
if (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
|
||||
hit->origin_protocol == LWSMPRO_REDIR_HTTPS)
|
||||
n = lws_snprintf((char *)end, 256, "%s%s",
|
||||
oprot[hit->origin_protocol & 1],
|
||||
hit->origin);
|
||||
else {
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
|
||||
if (!lws_hdr_total_length(wsi,
|
||||
WSI_TOKEN_HTTP_COLON_AUTHORITY))
|
||||
goto bail_nuke_ah;
|
||||
n = lws_snprintf((char *)end, 256,
|
||||
"%s%s%s/", oprot[!!lws_is_ssl(wsi)],
|
||||
lws_hdr_simple_ptr(wsi,
|
||||
WSI_TOKEN_HTTP_COLON_AUTHORITY),
|
||||
uri_ptr);
|
||||
} else
|
||||
n = lws_snprintf((char *)end, 256,
|
||||
"%s%s%s/", oprot[!!lws_is_ssl(wsi)],
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
|
||||
uri_ptr);
|
||||
}
|
||||
|
||||
lws_clean_url((char *)end);
|
||||
n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
|
||||
end, n, &p, end);
|
||||
if ((int)n < 0)
|
||||
goto bail_nuke_ah;
|
||||
|
||||
return lws_http_transaction_completed(wsi);
|
||||
}
|
||||
n = lws_http_redirect_hit(pt, wsi, hit, uri_ptr, uri_len, &ha);
|
||||
if (ha)
|
||||
return n;
|
||||
|
||||
/* basic auth? */
|
||||
|
||||
|
@ -1606,7 +1631,7 @@ lws_http_action(struct lws *wsi)
|
|||
}
|
||||
#endif
|
||||
|
||||
n = uri_len - lws_ptr_diff(s, uri_ptr); // (int)strlen(s);
|
||||
n = uri_len - lws_ptr_diff(s, uri_ptr);
|
||||
if (s[0] == '\0' || (n == 1 && s[n - 1] == '/'))
|
||||
s = (char *)hit->def;
|
||||
if (!s)
|
||||
|
@ -1866,6 +1891,7 @@ int
|
|||
lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
struct lws_context *context = lws_get_context(wsi);
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
#if defined(LWS_WITH_HTTP2)
|
||||
struct allocated_headers *ah;
|
||||
#endif
|
||||
|
@ -2005,6 +2031,32 @@ raw_transition:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* So he may have come to us requesting one or another kind
|
||||
* of upgrade from http... but we may want to redirect him at
|
||||
* http level. In that case, we need to check the redirect
|
||||
* situation even though he's not actually wanting http and
|
||||
* prioritize returning that if there is one.
|
||||
*/
|
||||
|
||||
{
|
||||
const struct lws_http_mount *hit = NULL;
|
||||
int uri_len = 0, ha, n;
|
||||
char *uri_ptr = NULL;
|
||||
|
||||
n = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
|
||||
if (n >= 0) {
|
||||
hit = lws_find_mount(wsi, uri_ptr, uri_len);
|
||||
if (hit) {
|
||||
n = lws_http_redirect_hit(pt, wsi, hit, uri_ptr,
|
||||
uri_len, &ha);
|
||||
if (ha)
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECT)) {
|
||||
lwsl_info("Changing to RAW mode\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue