Why nginx internal redirect is not happening
I'm pretty sure I missed an obvious thing but it's driving me crazy, I need other eyeballs..
I got an application with plugins were sources are organized like:
/app/plugins/foo/www/... that corresponds to my URL http://example.com/plugins/foo/...
I got the following snippet as nginx configuration:
location /plugins/foo {
alias /app/plugins/foo/www;
try_files $uri /index.php =404;
}
location ~* ^/plugins/foo/(.*\.php)$ {
alias /app/plugins/foo/www/$1;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
It works well for URLs like:
- http://example.com/plugins/foo/style/style.css
- http://example.com/plugins/foo/index.php
- http://example.com/plugins/foo/bar.php
But as soon as I'm trying to reach (front controller pattern):
- http://example.com/plugins/foo/?id=5
- http://example.com/plugins/foo/another/path
I got to download the php file.
According to the logs, the try_files seems to do what is expected but instead of internal redirect to php handler, it server the file as static:
2017/01/24 13:29:36 [debug] 20803#0: *6 using configuration "/plugins/foo"
2017/01/24 13:29:36 [debug] 20803#0: *6 http cl:-1 max:1048576
2017/01/24 13:29:36 [debug] 20803#0: *6 rewrite phase: 3
2017/01/24 13:29:36 [debug] 20803#0: *6 post rewrite phase: 4
2017/01/24 13:29:36 [debug] 20803#0: *6 generic phase: 5
2017/01/24 13:29:36 [debug] 20803#0: *6 generic phase: 6
2017/01/24 13:29:36 [debug] 20803#0: *6 generic phase: 7
2017/01/24 13:29:36 [debug] 20803#0: *6 generic phase: 8
2017/01/24 13:29:36 [debug] 20803#0: *6 access phase: 9
2017/01/24 13:29:36 [debug] 20803#0: *6 access phase: 10
2017/01/24 13:29:36 [debug] 20803#0: *6 post access phase: 11
2017/01/24 13:29:36 [debug] 20803#0: *6 try files phase: 12
2017/01/24 13:29:36 [debug] 20803#0: *6 http script var: "/plugins/git/"
2017/01/24 13:29:36 [debug] 20803#0: *6 trying to use file: "/" "/app/plugins/foo/www/"
2017/01/24 13:29:36 [debug] 20803#0: *6 trying to use file: "/index.php" "/app/plugins/foo/www/index.php"
2017/01/24 13:29:36 [debug] 20803#0: *6 try file uri: "/plugins/foo/index.php"
2017/01/24 13:29:36 [debug] 20803#0: *6 content phase: 13
2017/01/24 13:29:36 [debug] 20803#0: *6 content phase: 14
2017/01/24 13:29:36 [debug] 20803#0: *6 content phase: 15
2017/01/24 13:29:36 [debug] 20803#0: *6 content phase: 16
2017/01/24 13:29:36 [debug] 20803#0: *6 content phase: 17
2017/01/24 13:29:36 [debug] 20803#0: *6 content phase: 18
2017/01/24 13:29:36 [debug] 20803#0: *6 http filename: "/app/plugins/foo/www/index.php"
2017/01/24 13:29:36 [debug] 20803#0: *6 add cleanup: 000000000153FF70
2017/01/24 13:29:36 [debug] 20803#0: *6 http static fd: 13
2017/01/24 13:29:36 [debug] 20803#0: *6 http set discard body
2017/01/24 13:29:36 [debug] 20803#0: *6 xslt filter header
2017/01/24 13:29:36 [debug] 20803#0: *6 HTTP/1.1 200 OK
So question is: how to implement my front-end controller pattern in this situation ?
EDIT
With
location /plugins/foo {
alias /app/plugins/foo/www;
try_files $uri /plugins/foo/index.php?$args;
}
I got redirected to Core front-controller instead of the plugin ones:
2017/01/25 13:45:48 [debug] 14086#0: *197 using configuration "/plugins/foo"
...
2017/01/25 13:45:48 [debug] 14086#0: *197 try files phase: 12
2017/01/25 13:45:48 [debug] 14086#0: *197 http script var: "/plugins/foo/"
2017/01/25 13:45:48 [debug] 14086#0: *197 trying to use file: "/" "/app/plugins/foo/www/"
2017/01/25 13:45:48 [debug] 14086#0: *197 http script copy: "/plugins/git/index.php?"
2017/01/25 13:45:48 [debug] 14086#0: *197 http script var: "group_id=101"
2017/01/25 13:45:48 [debug] 14086#0: *197 trying to use file: "/index.php?group_id=101" "/app/plugins/foo/www/index.php?group_id=101"
====> ??? 2017/01/25 13:45:48 [debug] 14086#0: *197 internal redirect: "/index.php?group_id=101"
2017/01/25 13:45:48 [debug] 14086#0: *197 rewrite phase: 1
...
Why redirect to /index.php?group_id=101
when /app/plugins/foo/www/index.php?group_id=101
is valid ?
To avoid the long standing issue with using alias
together with try_files
, you could use an if
block instead (taking care to note usage restrictions). Note also, that $request_filename
is used instead of $document_root$fastcgi_script_name
to obtain aliased pathnames.
I have tested this example:
location ^~ /plugins/foo {
alias /app/plugins/foo/www;
if (!-e $request_filename) {
rewrite ^ /plugins/foo/index.php last;
}
location ~ \.php$ {
if (!-f $request_filename) {
rewrite ^ /plugins/foo/index.php last;
}
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}
- The
^~
modifier make thislocation
block take precedence over otherlocation
blocks at the same level (see this document). - The
rewrite
statement automatically appends arguments (see this document). - The nested
location
block handles PHP files within the aliased scope. - Always
include fastcgi_params;
before usingfastcgi_param
to avoid the latter being silently overwritten by the included file.