Opened 8 years ago

Closed 7 years ago

#803 closed enhancement (fixed)

proxy_pass differs in behavior if used with variable substitution

Reported by: s3tqr2w@… Owned by:
Priority: minor Milestone:
Component: documentation Version: 1.8.x
Keywords: docs Cc:
uname -a: Linux nginx 3.10.0-229.14.1.el7.x86_64 #1 SMP Tue Sep 15 15:05:51 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.8.0
built by gcc 4.8.2 20140120 (Red Hat 4.8.2-16) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_spdy_module --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Description (last modified by Maxim Dounin)

This may be desired, but it is not well documented, and caused me many hours of troubleshooting.

if using no-variables the uri is implicitly and transparently appended to the proxy_pass, i.e. a static definition:

location /test/ {
    proxy_pass http://upstream/test/;
}

Called with a URI of /test/this, will call the upstream URL: http://upstream/test/this. However, if a variable definition is used:

location /test/ {
    set $upstream_var upstream;
    proxy_pass http://$upstream_var/test/;
}

The same URL will ignore the URI, and only ever call http://upstream/test/

Changing the definition as follows resolves the problem, but is very counter-intuitive as the same command behaves differently which is not expected:

location /test/ {
    set $upstream_var upstream;
    proxy_pass http://$upstream_var$request_uri;
}

I don't know if there is a code fix to this--but it wasn't easy to figure out so perhaps the docs could somehow be more clear?

Change History (4)

comment:1 by Maxim Dounin, 8 years ago

Component: nginx-coreother
Description: modified (diff)
Keywords: docs added
Type: defectenhancement

Docs say (see http://nginx.org/r/proxy_pass):

A server name, its port and the passed URI can also be specified using variables ...

That is, if you use variables, the passed URI is expected to be specified, not a replacement URI part. This behaviour is required for original use case variables support in proxy_pass was added - to allow requests to any resource explicitly specified using variables.

While this may not be very natural behaviour for some other use cases like the one you describe, it's how it's expected to work and documented. Improving docs to be more explicit may make sense though.

Note well that in this particular case, when you don't need to change anything in the URI, it should be better to just use a server name, without an URI part. In this case nginx is smart enough to use original request URI regardless of whether you use variable or not:

location /test/ {
    set $upstream_var upstream;
    proxy_pass ​http://$upstream_var;
}

comment:2 by Maxim Dounin, 8 years ago

Component: otherdocumentation

comment:3 by Ruslan Ermilov <ru@…>, 7 years ago

In 1990:a108f1ff1690/nginx_org:

Better documented proxy_pass with variables (ticket #803).

comment:4 by Maxim Dounin, 7 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.