From 40c05b4a4ff7c8731c6ee23deea82416408dfc73 Mon Sep 17 00:00:00 2001 From: Otto van der Schaaf Date: Mon, 30 Nov 2015 20:00:08 +0100 Subject: [PATCH] location-header: Be careful with headers_out->location Only set headers_out->location when the upstream originally did as well. If the Location: header value involved starts with "/" nginx will absolutify it, ignoring any X-Forwarded-Proto header in the process. Fixes https://github.com/pagespeed/ngx_pagespeed/issues/819 (Confirmed: https://github.com/pagespeed/ngx_pagespeed/issues/1029) Hopefully fixes https://github.com/pagespeed/ngx_pagespeed/issues/711 --- src/ngx_pagespeed.cc | 15 +++++++++++---- src/ngx_pagespeed.h | 5 +++++ test/nginx_system_test.sh | 17 ++++++++++++++--- test/pagespeed_test.conf.template | 17 ++++++++++++++++- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/ngx_pagespeed.cc b/src/ngx_pagespeed.cc index 8645694e4..1f8f2e214 100644 --- a/src/ngx_pagespeed.cc +++ b/src/ngx_pagespeed.cc @@ -599,7 +599,10 @@ ngx_int_t copy_response_headers_to_ngx( } else if (STR_EQ_LITERAL(name, "Last-Modified")) { headers_out->last_modified = header; } else if (STR_EQ_LITERAL(name, "Location")) { - headers_out->location = header; + ps_request_ctx_t* ctx = ps_get_request_context(r); + if (ctx->location_field_set) { + headers_out->location = header; + } } else if (STR_EQ_LITERAL(name, "Server")) { headers_out->server = header; } else if (STR_EQ_LITERAL(name, "Content-Length")) { @@ -1264,6 +1267,7 @@ ngx_int_t ps_decline_request(ngx_http_request_t* r) { ctx->driver->Cleanup(); ctx->driver = NULL; + ctx->location_field_set = false; // re init ctx ctx->html_rewrite = true; @@ -1833,6 +1837,7 @@ ngx_int_t ps_resource_handler(ngx_http_request_t* r, ctx->recorder = NULL; ctx->url_string = url_string; + ctx->location_field_set = false; // Set up a cleanup handler on the request. ngx_http_cleanup_t* cleanup = ngx_http_cleanup_add(r, 0); @@ -1902,12 +1907,12 @@ ngx_int_t ps_resource_handler(ngx_http_request_t* r, bool is_proxy = false; GoogleString mapped_url; GoogleString host_header; - + if (options->domain_lawyer()->MapOriginUrl( url, &mapped_url, &host_header, &is_proxy) && is_proxy) { ps_create_base_fetch(ctx, request_context, request_headers.release(), kPageSpeedProxy); - + RewriteDriver* driver; if (custom_options.get() == NULL) { driver = cfg_s->server_context->NewRewriteDriver( @@ -1926,7 +1931,7 @@ ngx_int_t ps_resource_handler(ngx_http_request_t* r, return ps_async_wait_response(r); } - + } if (html_rewrite) { @@ -2233,6 +2238,8 @@ ngx_int_t ps_html_rewrite_header_filter(ngx_http_request_t* r) { } ps_strip_html_headers(r); + // See https://github.com/pagespeed/ngx_pagespeed/issues/819 + ctx->location_field_set = r->headers_out.location != NULL; // TODO(jefftk): is this thread safe? copy_response_headers_from_ngx(r, ctx->base_fetch->response_headers()); diff --git a/src/ngx_pagespeed.h b/src/ngx_pagespeed.h index 00fd00e34..cae895a8a 100644 --- a/src/ngx_pagespeed.h +++ b/src/ngx_pagespeed.h @@ -103,6 +103,11 @@ typedef struct { // We need to remember the URL here as well since we may modify what NGX // gets by stripping our special query params and honoring X-Forwarded-Proto. GoogleString url_string; + + // We need to remember if the upstream had headers_out->location set, because + // we should mirror that when we write it back. nginx may absolutify + // Location: headers that start with '/' without regarding X-Forwarded-Proto. + bool location_field_set; } ps_request_ctx_t; ps_request_ctx_t* ps_get_request_context(ngx_http_request_t* r); diff --git a/test/nginx_system_test.sh b/test/nginx_system_test.sh index 547901c82..ee976f5f2 100644 --- a/test/nginx_system_test.sh +++ b/test/nginx_system_test.sh @@ -322,8 +322,8 @@ fi # # TODO(sligicki): When the prioritize critical css race condition is fixed, the # two prioritize_critical_css tests no longer need to be listed here. -# TODO(oschaaf): Now that we wait after we send a SIGHUP for the new worker -# process to handle requests, check if we can remove more from the expected +# TODO(oschaaf): Now that we wait after we send a SIGHUP for the new worker +# process to handle requests, check if we can remove more from the expected # failures here under valgrind. if $USE_VALGRIND; then PAGESPEED_EXPECTED_FAILURES+=" @@ -514,6 +514,17 @@ check $WGET_DUMP -O $FETCHED $HEADERS $URL # When enabled, we respect X-Forwarded-Proto and thus list base as https. check fgrep -q '