Opened 8 years ago
Closed 8 years ago
#1498 closed defect (duplicate)
Named and capture variables cannot be used together
| Reported by: | Owned by: | ||
|---|---|---|---|
| Priority: | minor | Milestone: | |
| Component: | nginx-module | Version: | 1.12.x |
| Keywords: | if set rewrite variable | Cc: | |
| uname -a: | Linux servername 4.9.0-5-amd64 #1 SMP Debian 4.9.65-3+deb9u2 (2018-01-04) x86_64 GNU/Linux | ||
| nginx -V: |
nginx version: nginx/1.12.1
built by gcc 4.9.2 (Debian 4.9.2-10) built with OpenSSL 1.0.2j 26 Sep 2016 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=/run/nginx.pid --lock-path=/run/lock/nginx.lock --http-client-body-temp-path=/run/shm/body_temp --http-proxy-temp-path=/run/shm/proxy_temp --http-fastcgi-temp-path=/run/shm/fastcgi_temp --http-uwsgi-temp-path=/run/shm/uwsgi_temp --http-scgi-temp-path=/run/shm/scgi_temp --with-http_ssl_module --with-http_realip_module --with-http_sub_module --with-http_dav_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --with-mail --with-http_v2_module --with-http_geoip_module --with-select_module --with-http_auth_request_module --with-poll_module --with-debug |
||
Description
Say I want to rewrite URI differently depending on something like client cookie. So I create a map (remembering that if is evil):
map $cookie_foo $my_var {
1 bar;
default baz;
}
And later I try to do the obvious rewrite:
location / {
rewrite ^/(.*) /$my_var/$1 break;
proxy_pass http://backend;
}
... and it's tricky. In my case, if map returns default value (baz), everything works as planned. But if map returns non-default value (bar), $1 in rewrite expands to empty string no matter what URI really is.
More over, this magic happens not only in rewrite, but in set too, for example, I tried the following:
if ( $uri ~ ^/(.*) ) {
set $rewrite_path $my_var/$1;
rewrite /.* /$rewrite_path break;
}
That doesn't work either. But the next piece of code finally works fine for me:
if ( $uri ~ ^/(.*) ) {
set $tmp_var $1;
rewrite /.* /$my_var/$tmp_var break;
}
But it's ugly AF.
Can you please fix it so that the original version (rewrite ^/(.*) /$my_var/$1 break;) works? Or please tell me what part of the documentation describes why this is impossible (but nevertheless works in some cases).
Debug log for both cases:
1) when map returns default value:
2018/03/02 19:25:09 [debug] 23380#0: *495 http map: "0" "baz" 2018/03/02 19:25:09 [debug] 23380#0: *495 http script copy: "/" 2018/03/02 19:25:09 [debug] 23380#0: *495 http script var: "baz" 2018/03/02 19:25:09 [debug] 23380#0: *495 http script copy: "/" 2018/03/02 19:25:09 [debug] 23380#0: *495 http script capture: "mstatic/build/main.bundle.js" 2018/03/02 19:25:09 [debug] 23380#0: *495 http script regex end 2018/03/02 19:25:09 [notice] 23380#0: *495 rewritten data: "/baz/mstatic/build/main.bundle.js"
URI is captured and capture variable is expanded all right - works as expected
2) when map returns non-default value:
2018/03/02 19:23:20 [debug] 23371#0: *74 http map: "1" "bar" 2018/03/02 19:23:20 [debug] 23371#0: *74 http script copy: "/" 2018/03/02 19:23:20 [debug] 23371#0: *74 http script var: "bar" 2018/03/02 19:23:20 [debug] 23371#0: *74 http script copy: "/" 2018/03/02 19:23:20 [debug] 23371#0: *74 http script capture: "" 2018/03/02 19:23:20 [debug] 23371#0: *74 http script regex end 2018/03/02 19:23:20 [notice] 23371#0: *74 rewritten data: "/bar/"
URI was the same, but it says that capture is empty, so somebody is lying here.
Change History (3)
comment:1 by , 8 years ago
comment:3 by , 8 years ago
| Resolution: | → duplicate |
|---|---|
| Status: | new → closed |
Thanks for confirming. Closing this as duplicate of #564.

In the particular configuration with the
maplisted there should be no problem. The problem you are describing is likely to happen when using regular expressions inmap, see #564.