#1504 closed defect (invalid)
Redirect issue when equaling $request_uri and $uri with unicode characters
| Reported by: | Owned by: | ||
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | nginx-core | Version: | 1.13.x |
| Keywords: | Cc: | ||
| uname -a: | Linux 541bb2841bf8 4.9.60-linuxkit-aufs #1 SMP Mon Nov 6 16:00:12 UTC 2017 x86_64 GNU/Linux | ||
| nginx -V: | nginx version: nginx/1.13.9 | ||
Description
Nginx version: nginx:latest from docker (v1.13, tested in 1.12 too)
server {
#root /var/www/html/public;
location / {
set $test_uri https://$host$request_uri;
if ($test_uri != https://$host$uri) {
#rewrite ^ $scheme://$host$uri$is_args$args? permanent;
rewrite ^ http://test?uri=$uri&request_uri=$request_uri&test_uri=$test_uri;
}
root /usr/share/nginx/html;
index index.html index.htm;
}
}
- curl -I
http://localhost:8081/čřčžřčž - you get
http://test/?uri=/%C4%8D%C5%99%C4%8D%C5%BE%C5%99%C4%8D%C5%BE&request_uri=/%C4%8D%C5%99%C4%8D%C5%BE%C5%99%C4%8D%C5%BE&test_uri=https://localhost/%C4%8D%C5%99%C4%8D%C5%BE%C5%99%C4%8D%C5%BE
Attachments (1)
Change History (9)
by , 8 years ago
| Attachment: | nginx-redirect-unicode-bug.png added |
|---|
comment:1 by , 8 years ago
comment:2 by , 8 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
It is not clear what are you trying to do, but the if directive when used with the = and != operators only allows comparing a variable with a string. As such, the condition used is always true, as you compare with the https://$host$uri static string.
comment:3 by , 8 years ago
this example will solve for example duplicates versions of urls
http://example.com/test//test2/ will make redirect to http://example.com/test/test2/
set $test_uri $scheme://$host$request_uri;
if ($test_uri != $scheme://$host$uri) {
rewrite ^ $scheme://$host$uri$is_args$args? permanent;
}
but
if your url contains nonASCI symbols like ůěščřžýáíé ... condition matcher will do infinite redirect because if (/%C4 != /%C4) => true
it is bug in equal condition matcher
comment:4 by , 8 years ago
| Resolution: | invalid |
|---|---|
| Status: | closed → reopened |
comment:5 by , 8 years ago
| Resolution: | → invalid |
|---|---|
| Status: | reopened → closed |
Ah, I was actually wrong: the second operand of != can contain variables, hence the test actually works.
You misunderstand the difference between $uri and $request_uri though. Among other things, $uri is unescaped, hence it is never equal to $request_uri if the latter contains any escaped characters. This is obvious if you'll actually try to use curl with an actual escaped URL and the configuration you've provided:
$ curl -I http://127.0.0.1:8080/%C4%8D HTTP/1.1 302 Moved Temporarily Server: nginx/1.13.10 Date: Tue, 13 Mar 2018 02:46:40 GMT Content-Type: text/html Content-Length: 162 Connection: keep-alive Location: http://test?uri=/č&request_uri=/%C4%8D&test_uri=https://127.0.0.1/%C4%8D
Note that unescaped non-ASCII characters are not permitted in URIs, and browsers will escape them automatically, confusing things.
follow-up: 7 comment:6 by , 8 years ago
and what about this forgotten? patch 5years ago?
http://nginx.2469901.n2.nabble.com/ngx-unescape-uri-bug-td7584520.html
I think there should be 2 variables for $uri: $uri_escaped and $uri_unescaped
comment:7 by , 8 years ago
Replying to insekticid@…:
and what about this forgotten? patch 5years ago?
http://nginx.2469901.n2.nabble.com/ngx-unescape-uri-bug-td7584520.html
The "patch" in question doesn't really make sense - see my response there. And, more importantly, it is completely unrelated to your case, as the ngx_unescape_uri() function is not used to unescape request URIs, it happens in the ngx_http_parse_complex_uri() function (and it rejects invalid escaping).
I think there should be 2 variables for $uri: $uri_escaped and $uri_unescaped
See ticket #52.

the same problem with this config
server { #root /var/www/html/public; location / { set $test_uri https://$host$request_uri; set $test_uri2 https://$host$request_uri; if ($test_uri != test_uri2) { #rewrite ^ $scheme://$host$uri$is_args$args? permanent; rewrite ^ http://test?uri=$uri&request_uri=$request_uri&test_uri=$test_uri; } root /usr/share/nginx/html; index index.html index.htm; } }