Opened 14 years ago
Last modified 2 years ago
#86 accepted defect
the "if" directive have problems in location context
| Reported by: | s "hr" berder | Owned by: | somebody |
|---|---|---|---|
| Priority: | minor | Milestone: | |
| Component: | nginx-core | Version: | |
| Keywords: | Cc: | ||
| uname -a: | Linux bjs-fl-dev-web06 2.6.18-274.12.1.el5xen #1 SMP Tue Nov 29 14:18:21 EST 2011 x86_64 x86_64 x86_64 GNU/Linux | ||
| nginx -V: |
nginx version: nginx/0.8.55
built by gcc 4.1.2 20080704 (Red Hat 4.1.2-51) TLS SNI support disabled configure arguments: --user=nginx --group=nginx --prefix=/usr/share/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 --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/subsys/nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module --with-http_perl_module --with-mail --with-file-aio --with-mail_ssl_module --with-ipv6 --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' |
||
Description
To start, I'm doing tricky stuff so please don't point out at the weird things and stay focused on the issue at hand.
I'm mixing a configuration with userdir and symfony2 (http://wiki.nginx.org/Symfony) for a development environment, php is using php-fpm and a unix socket.
The userdir configuration is classic, all your files in ~user/public_html/ will be accessible through http://server/~user/.
I add to this the fact that if you create a folder ~user/public_html/symfony/ and put a symfony project in it (~user/public_html/symfony/project/) it will have the usual symfony configuration applied (rewrites and fastcgi path split).
Here you go for the configuration :
# match 1:username, 2:project name, 3:the rest
location ~ ^/~(.+?)/symfony/(.+?)/(.+)$ {
alias /home/$1/public_html/symfony/$2/web/$3;
if (-f $request_filename) {
break;
}
# if no app.php or app_dev.php, redirect to app.php (prod)
rewrite ^/~(.+?)/symfony(/.+?)/(.+)$ /~$1/symfony/$2/app.php/$3 last;
}
# match 1:username, 2:project name, 3:env (prod/dev), 4:trailing ('/' or
# end)
location ~ ^/~(.+?)/symfony(/.+)/(app|app_dev)\.php(/|$) {
root /home/$1/public_html/symfony$2/web;
# fake $request_filename
set $req_filename /home/$1/public_html/symfony$2/web/$3.php;
include fastcgi_params;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $req_filename;
fastcgi_pass unix:/tmp/php-fpm.sock;
}
The second block (PHP backend) works on its own. The first block (files direct access) works on its own.
You can see that I already had a problem with PHP but went around it with creating my own variable.
To help understand, here is a sample of a symfony project layout (I removed some folders to help the comprehension):
project/
src/
[... my php code ...]
web/
app_dev.php
app.php
favicon.ico
If I try to access http://server/~user/symfony/project/favicon.ico I see this in the logs :
2012/01/17 16:36:25 [error] 27736#0: *1 open() "/home/user/public_html/symfony/project/web/favicon.icoavicon.ico" failed (2: No such file or directory), client: 10.11.60.36, server: server, request: "HEAD /~user/symfony/project/favicon.ico HTTP/1.1", host: "server"
If I remove the block that tests $request_filename, it works but I have to remove the rewrite as well.
The server is a CentOS 5.7 and the nginx is coming from the EPEL repository.
Unfortunately my C skills are down the floor so I can't really provide a better understanding of the problem. I tried to poke around the code but with not much luck.
Change History (9)
comment:1 by , 14 years ago
| Status: | new → accepted |
|---|---|
| Summary: | alias and $request_filename don't play along → the "if" directive have problems in location context |
| Version: | 0.8.x |
comment:2 by , 12 years ago
| sensitive: | → 0 |
|---|
A particular case with regex location + alias + if is resolved by c985d90a8d1f.
Leaving the ticket open as there are other cases which still need to be fixed, see http://wiki.nginx.org/IfIsEvil.
comment:4 by , 9 years ago
See also #633, which is basically identical to the same problem with if:
# try_files wont work due to if
location /if-try-files {
try_files /file @fallback;
set $true 1;
if ($true) {
# nothing
}
}
In both cases try_files is not inherited into an implicit location created with if / limit_except and this results in unexpected behaviour.

This is one of the known problems with the "if" directive used in a location context, see http://wiki.nginx.org/IfIsEvil. Reduced test case is as follows (copied from the wiki page in question):
# alias with captures isn't correcly inherited into implicit nested # location created by if location ~* ^/if-and-alias/(?<file>.*) { alias /tmp/$file; set $true 1; if ($true) { # nothing } }Workaround is not to use if, or use it in a safe way, see the wiki page in question.