Home > database >  Nginx rewrite rule omit forward slash (/) when its first in encoded url
Nginx rewrite rule omit forward slash (/) when its first in encoded url

Time:09-26

i am trying use Nginx rewrite. somehow its deletes the / key when its first in string

nginx/1.21.3

rewrite rule:

#nginx not relevant conf here
location / {
    rewrite ^(.*)data/([0-9] )/(. )?$ $1processor.php?key=$2&data=$3 last;
}
#nginx not relevant conf here

when i use this rewrite rule for any url i tested it was okay. when i tried url like the example below it somehow omitted the / in the beginning.

https://example.com/data/9//*-+.`!@#$%^&*()_+`-=[];'\,./{}:"|<>?

when i reloaded nginx with notices and rewrite_log=on; i got the output:

2021/09/25 13:08:29 [notice] 528#528: *11710 "^(.*)data/([0-9] )/(. )?$" matches "/data/199/*- .`!@#$%^&*()_ `-=[];'\,./{}:"|<>?", client: 192.168.255.107, server: localhost, request: "GET /data/199//*-+.`!@#$%^&*()_+`-=[];'\,./{}:"|<>? HTTP/2.0", host: "example.com", referrer: "https://example.com/"

php (8.0.10) $_GET["data"] output is (as you can see without / thus not exact math):

*- .`!@#$%^&*()_ `-=[];'\,./{}:"|<>?

how can i solve it?

CodePudding user response:

Both rewrite and location directives works with so-called normalized URI:

The matching is performed against a normalized URI, after decoding the text encoded in the “%XX” form, resolving references to relative path components “.” and “..”, and possible compression of two or more adjacent slashes into a single slash.

This means that on the first stage your URL /data/9//*-+.`!@#$%^&*()_+`-=[];'\,./{}:"|<>? gets URL-decoded:

/data/9//*- .`!@#$%^&*()_ `-=[];'\,./{}:"|<>?

and on the second stage two adjacent slashes getting compressed into the one:

/data/9/*- .`!@#$%^&*()_ `-=[];'\,./{}:"|<>?

Exactly the above string is subject to test for rewrite directive thus leading to missing of the first URL-encoded slash. However you can use the $request_uri variable which contains the request URI in a non-modified form. You can use either

if ($request_uri ~ ^(?<prefix>.*/)data/(?<key>\d )/(?<data>[^?] )) {
    rewrite ^ ${prefix}processor.php?key=$key&data=$data;
}

block to be placed under server context or

location /
    if ($request_uri ~ ^(?<prefix>.*/)data/(?<key>\d )/(?<data>[^?] )) {
        rewrite ^ ${prefix}processor.php?key=$key&data=$data last;
    }
    ...
}

block placed under location context.

  • Related