From 7e2c3851bf838bc5d0aaf5a8b64206761f3e3d0f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 15 Apr 2016 20:09:36 +0800 Subject: [PATCH] redirects need fake content metadata Chrome deals with it without on desktop, but Android chrome waits for the connection to time out before actioning the redirect, since it feels there might be html payload coming. Signed-off-by: Andy Green --- lib/header.c | 39 +++++++++++++++++++++++++++++++++++++++ lib/libwebsockets.h | 4 ++++ lib/server.c | 29 ++++++----------------------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/lib/header.c b/lib/header.c index 457f544a..70058d19 100644 --- a/lib/header.c +++ b/lib/header.c @@ -250,3 +250,42 @@ lws_return_http_status(struct lws *wsi, unsigned int code, return m != n; } + +LWS_VISIBLE int +lws_http_redirect(struct lws *wsi, const unsigned char *loc, int len, + unsigned char **p, unsigned char *end) +{ + unsigned char *start = *p; + int n; + + if (lws_add_http_header_status(wsi, 301, p, end)) + return -1; + + if (lws_add_http_header_by_token(wsi, + WSI_TOKEN_HTTP_LOCATION, + loc, len, p, end)) + return -1; + /* + * if we're going with http/1.1 and keepalive, + * we have to give fake content metadata so the + * client knows we completed the transaction and + * it can do the redirect... + */ + if (lws_add_http_header_by_token(wsi, + WSI_TOKEN_HTTP_CONTENT_TYPE, + (unsigned char *)"text/html", 9, + p, end)) + return -1; + if (lws_add_http_header_by_token(wsi, + WSI_TOKEN_HTTP_CONTENT_LENGTH, + (unsigned char *)"0", 1, p, end)) + return -1; + + if (lws_finalize_http_header(wsi, p, end)) + return -1; + + n = lws_write(wsi, start, *p - start, + LWS_WRITE_HTTP_HEADERS); + + return n; +} diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 0d90c55a..0f6687dd 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1643,6 +1643,10 @@ lws_add_http_header_status(struct lws *wsi, unsigned int code, unsigned char **p, unsigned char *end); +LWS_VISIBLE LWS_EXTERN int +lws_http_redirect(struct lws *wsi, const unsigned char *loc, int len, + unsigned char **p, unsigned char *end); + LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_http_transaction_completed(struct lws *wsi); diff --git a/lib/server.c b/lib/server.c index 880cc4af..fc11a74d 100644 --- a/lib/server.c +++ b/lib/server.c @@ -424,7 +424,6 @@ lws_http_action(struct lws *wsi) lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, wsi->context->timeout_secs); #ifdef LWS_OPENSSL_SUPPORT -#if 0 if (wsi->redirect_to_https) { /* * we accepted http:// only so we could redirect to @@ -436,23 +435,17 @@ lws_http_action(struct lws *wsi) 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; + n = sprintf((char *)end, "https://%s/", lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST)); - 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); + + n = lws_http_redirect(wsi, end, n, &p, end); if ((int)n < 0) goto bail_nuke_ah; return lws_http_transaction_completed(wsi); } #endif -#endif #ifdef LWS_WITH_ACCESS_LOG /* @@ -563,14 +556,10 @@ lws_http_action(struct lws *wsi) "http://", "https://" }; - lwsl_err("Doing 301 '%s' org %s\n", s, hit->origin); + lwsl_notice("Doing 301 '%s' org %s\n", s, hit->origin); 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_debug("**** %s", hit->origin); /* > at start indicates deal with by redirect */ if (hit->origin_protocol & 4) @@ -582,14 +571,8 @@ lws_http_action(struct lws *wsi) "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); + + n = lws_http_redirect(wsi, end, n, &p, end); if ((int)n < 0) goto bail_nuke_ah;