Bad side effect of (even unmatched) nested regex locations in regex locations with anonymous captures with try_files/alias
Christoph Schug
chris+nginx at schug.net
Thu Aug 2 08:38:15 UTC 2012
Hello!
I have another interesting scenario ;-) Given is following minimized
test case
server {
listen 80;
server_name t2.example.com;
root /data/web/t2.example.com/htdoc;
location ~ ^/bar(/.*)? {
alias
/data/web/t2.example.com/htdoc/foo$1;
try_files '' =404;
}
location ~ ^/bla(/.*)? {
alias
/data/web/t2.example.com/htdoc/foo$1;
try_files '' =404;
location ~ child_of_bla(?P<x>.*)$ {
return 418;
}
}
}
on Nginx 1.3.4 (but not specific to that version)
# nginx -V
nginx version: nginx/1.3.4
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx
--conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/sbin/nginx
--http-log-path=/var/log/nginx/access.log
--error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid
--user=nginx --group=nginx --with-openssl=openssl-1.0.1c --with-debug
--with-http_stub_status_module --with-http_ssl_module --with-ipv6
and follow file system layout
$ find /data/web/t2.example.com/htdoc/
/data/web/t2.example.com/htdoc/
/data/web/t2.example.com/htdoc/foo
/data/web/t2.example.com/htdoc/foo/quux.txt
Plain access to quux.txt works of course
$ curl -s -D - -H 'Host: t2.example.com' http://127.0.0.1/foo/quux.txt
HTTP/1.1 200 OK
Server: nginx/1.3.4
Date: Thu, 02 Aug 2012 08:27:57 GMT
Content-Type: text/plain
Content-Length: 5
Last-Modified: Thu, 02 Aug 2012 07:15:43 GMT
Connection: keep-alive
ETag: "501a291f-5"
Accept-Ranges: bytes
QUUX
Access to location /bar works as well as expected
$ curl -s -D - -H 'Host: t2.example.com' http://127.0.0.1/bar/quux.txt
HTTP/1.1 200 OK
Server: nginx/1.3.4
Date: Thu, 02 Aug 2012 08:28:10 GMT
Content-Type: application/octet-stream
Content-Length: 5
Last-Modified: Thu, 02 Aug 2012 07:15:43 GMT
Connection: keep-alive
ETag: "501a291f-5"
Accept-Ranges: bytes
QUUX
but it breaks when the location of the same style has a nested location
(which might be even unmatched; here this child_of_bla thingy), which
also does a regex capture (doesn't matter whether this is an anonymous
or named capture)
$ curl -s -D - -H 'Host: t2.example.com' http://127.0.0.1/bla/quux.txt
HTTP/1.1 404 Not Found
Server: nginx/1.3.4
Date: Thu, 02 Aug 2012 08:28:13 GMT
Content-Type: text/html
Content-Length: 168
Connection: keep-alive
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.3.4</center>
</body>
</html>
Nginx doesn't even seem to process anyhting in the 'try files phase'
according to the debug log.
2012/08/02 10:28:13 [debug] 15741#0: *17 http process request line
2012/08/02 10:28:13 [debug] 15741#0: *17 http request line: "GET
/bla/quux.txt HTTP/1.1"
2012/08/02 10:28:13 [debug] 15741#0: *17 http uri: "/bla/quux.txt"
2012/08/02 10:28:13 [debug] 15741#0: *17 http args: ""
2012/08/02 10:28:13 [debug] 15741#0: *17 http exten: "txt"
2012/08/02 10:28:13 [debug] 15741#0: *17 http process request header
line
2012/08/02 10:28:13 [debug] 15741#0: *17 http header: "User-Agent:
curl/7.19.7 (i386-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.1.0
zlib/1.2.3 libidn/1.18 libssh2/1.2.2"
2012/08/02 10:28:13 [debug] 15741#0: *17 http header: "Accept: */*"
2012/08/02 10:28:13 [debug] 15741#0: *17 http header: "Host:
t2.example.com"
2012/08/02 10:28:13 [debug] 15741#0: *17 http header done
2012/08/02 10:28:13 [debug] 15741#0: *17 rewrite phase: 0
2012/08/02 10:28:13 [debug] 15741#0: *17 test location: ~ "^/bar(/.*)?"
2012/08/02 10:28:13 [debug] 15741#0: *17 test location: ~ "^/baz(/.*)?"
2012/08/02 10:28:13 [debug] 15741#0: *17 using configuration ""
2012/08/02 10:28:13 [debug] 15741#0: *17 http cl:-1 max:1048576
2012/08/02 10:28:13 [debug] 15741#0: *17 rewrite phase: 2
2012/08/02 10:28:13 [debug] 15741#0: *17 post rewrite phase: 3
2012/08/02 10:28:13 [debug] 15741#0: *17 generic phase: 4
2012/08/02 10:28:13 [debug] 15741#0: *17 generic phase: 5
2012/08/02 10:28:13 [debug] 15741#0: *17 access phase: 6
2012/08/02 10:28:13 [debug] 15741#0: *17 access phase: 7
2012/08/02 10:28:13 [debug] 15741#0: *17 post access phase: 8
2012/08/02 10:28:13 [debug] 15741#0: *17 try files phase: 9
(nothing happens here?)
2012/08/02 10:28:13 [debug] 15741#0: *17 content phase: 10
2012/08/02 10:28:13 [debug] 15741#0: *17 content phase: 11
2012/08/02 10:28:13 [debug] 15741#0: *17 content phase: 12
2012/08/02 10:28:13 [debug] 15741#0: *17 http filename:
"/data/web/t2.example.com/htdoc/bla/quux.txt"
2012/08/02 10:28:13 [error] 15741#0: *17 open()
"/data/web/t2.example.com/htdoc/bla/quux.txt" failed (2: No such file or
directory), client: 127.0.0.1, server: t2.example.com, request: "GET
/bla/quux.txt HTTP/1.1", host: "t2.example.com"
2012/08/02 10:28:13 [debug] 15741#0: *17 http finalize request: 404,
"/bla/quux.txt?" a:1, c:1
2012/08/02 10:28:13 [debug] 15741#0: *17 http special response: 404,
"/bla/quux.txt?"
2012/08/02 10:28:13 [debug] 15741#0: *17 http set discard body
2012/08/02 10:28:13 [debug] 15741#0: *17 HTTP/1.1 404 Not Found
Interestingly enough it works when I change the anonymous capture for
/bar to a named one and replace the $1 in the alias by that named
variable.
Is this expected behavior or should I rather assume "anonymous captures
are evil"?
-cs
More information about the nginx
mailing list