Opened 5 weeks ago

Closed 5 weeks ago

#2595 closed defect (invalid)

Unexpected behaviour between ngx_http_rewrite_module and ngx_http_core_module

Reported by: Riddr Inc Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.25.x
Keywords: rewrite, variable Cc:
uname -a: Linux a34dd1683ec5 6.4.16-linuxkit #1 SMP PREEMPT_DYNAMIC Thu Nov 16 10:55:59 UTC 2023 x86_64 Linux
nginx -V: nginx version: nginx/1.25.3



I'm experiencing weird issue involving nginx variables, rewrite module and the location directive from the http_core module. I'm trying to use variable's value as a rewrite URI. The thing is when I use query parameters in the variable value nginx location directive is trying to access the file with the query arguments included.

For example, I'm having the following configuration in my server context.

set $test /test.php?test=1;
rewrite ^/my/test$ $test last;

When trying to access the /my/test location I get the following error message:

GET /my/test HTTP/2.0" 404
open() "/app/public_html/test.php?test=1" failed (2: No such file or directory)

When not using variable for the replacement uri everything works fine:

rewrite ^/my/test$ /test.php?test=1 last;
GET /my/test HTTP/2.0" 200

Is this intentional behaviour due to how nginx is compiling the rewrite directives at configuration stage, or I've stumbled upon some bug?

Change History (1)

comment:1 by Maxim Dounin, 5 weeks ago

Resolution: invalid
Status: newclosed
Summary: Unexpected behaviour between ngx_stream_set_module, ngx_http_rewrite_module and ngx_http_core_moduleUnexpected behaviour between ngx_http_rewrite_module and ngx_http_core_module

The rewrite directive only interprets the ? character as an arguments separator (or do-not-add-arguments flag) when it is used literally in the replacement string. That is, everything before the ? character is interpreted as a URI path, and everything after it as arguments, and you can use variables in both parts. That is, something like this will work fine:

set $test '/test.php';
set $test_args 'test=1';
rewrite ^/my/test$ $test?$test_args? last;

But when the ? character appears in the variables in either part, as in your first snippet, it is not interpreted as a separator and instead goes directly into the relevant URI part. In your example, it goes to the URI path, $uri, and the <root>/test.php?test=1 file is returned (or the 404 error if the file does not exists).

While this behaviour might be somewhat non-intuitive, and probably underdocumented, this is how it is expected to work.

Note: See TracTickets for help on using tickets.