Opened 5 years ago

Closed 4 years ago

#874 closed defect (wontfix)

Incorrect $upstream_http_location value

Reported by: sunnybear@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.9.x
Keywords: Cc:
uname -a: Linux node.airee.ru 2.6.32-504.23.4.el6.centos.plus.x86_64 #1 SMP Wed Jun 10 13:09:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.9.5
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --add-module=/root/ngx_pagespeed-release-1.7.30.2-beta --add-module=/root/ngx_devel_kit --add-module=/root/set-misc-nginx-module --add-module=/root/nginx-length-hiding-filter-module --add-module=/root/nginx-http-rdns --add-module=/root/ngx_http_substitutions_filter_module --with-cc-opt='-DNGX_HAVE_ACCEPT4=0 -DTCP_FASTOPEN=23 -O2 -fomit-frame-pointer' --with-ipv6 --with-http_gunzip_module --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module --with-http_sub_module --without-http_geo_module --without-http_access_module --without-http_auth_basic_module --without-http_autoindex_module --without-http_empty_gif_module --without-http_memcached_module --without-http_referer_module --without-http_scgi_module --without-http_split_clients_module --without-http_uwsgi_module

Description

While accessing $upstream_http_location after proxied request it contains \x00AB at the end (it seems AB are the last 2 symbols of actual $upstream_http_location).

Example (response headers):

< HTTP/1.1 302 Moved Temporarily
< Date: Wed, 06 Jan 2016 13:32:43 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Location: http://xn--80aqc2a.xn--p1ai/loop.redirects.php
< Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval' < UpstreamHTTPLocation: http://xn--80aqc2a.xn--p1ai/loop.redirects.phphp

\x00hp are added to current upstream Location HTTP header

Change History (7)

comment:1 by Maxim Dounin, 5 years ago

When the proxy_redirect directive is used to rewrite returned Location headers, it does the replacement in place if possible, overwriting original value of the header as available via the $upstream_http_location variable. This is an optimization to avoid an extra memory allocation.

If it's the problem in your use case, please provide more details on how you use $upstream_http_location. We can consider removing the optimization if causes more harm than good.

comment:2 by sunnybear@…, 5 years ago

Yes, it seems proxy_redirect breaks the variable $upstream_http_location. Without this directive Location is modified accordingly to actual port requested:
http://xn--80aqc2a.xn--p1ai:81/loop.redirects.php

So proxy_redirect fixes the port (:81 -> ""), but breaks the variable. Can you please fix this?

comment:3 by Maxim Dounin, 5 years ago

As previously explained, this is an optimization to avoid an extra memory allocation. If it's the problem in your use case, please provide more details on how you use $upstream_http_location. We can consider removing the optimization if causes more harm than good.

comment:4 by sunnybear@…, 5 years ago

Can you please just fix the length of variable (it's incorrect after optimization)? You shouldn't remove the optimization itself.

Use case: set cookie with Location header value to prevent loop redirects or fix them somehow (with client cookie with previous Location sent). Now the previous Location (from cookie) doesn't concide with current Location (from upstream variable).

comment:5 by Maxim Dounin, 5 years ago

Correct changed value is available via the $sent_http_location variable, consider using it instead.

comment:6 by sunnybear@…, 5 years ago

Good idea. But suddenly access to $sent_http_location breaks (nulls) it.

I.e.
add_header X-Location $sent_http_location;

OK

set $stored_http_location $sent_http_location;
add_header X-Location $sent_http_location;

Nothing

add_header X-Location $sent_http_location;
if ($sent_http_location = 'redirect.value')
{
return 503;
}

Nothing

This happens both with upstream_ and sent_ variables. So it's not the initial topic (Initial topic solution - to use sent_ variables instead of upstream_) but another question (or issue?).

comment:7 by Maxim Dounin, 4 years ago

Resolution: wontfix
Status: newclosed

The "set" and "if" directives cannot be used to modify variables not yet available when these directives are executred. The directives are executed when nginx selects a location to handle the request, see docs. The $sent_* variables are only available when the response is actually being sent, and this happens later. Using not-yet-available variables will result in an empty value being cached, and this is what breaks things for you.

The $sent_* variables, however, can be used in the add_header when response is being returned and response headers are already known. If needed, it can be modified using variable-based processing, e.g., map or perl_set.

Note: See TracTickets for help on using tickets.