Opened 7 years ago

Closed 7 years ago

#1498 closed defect (duplicate)

Named and capture variables cannot be used together

Reported by: tiandrey@… 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 Maxim Dounin, 7 years ago

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

comment:2 by tiandrey@…, 7 years ago

That must be the problem. Thanks.

comment:3 by Maxim Dounin, 7 years ago

Resolution: duplicate
Status: newclosed

Thanks for confirming. Closing this as duplicate of #564.

Note: See TracTickets for help on using tickets.