Nginx Rewriting : PHP file inside of Location directive not served

I am trying to redirect a subdirectory to a php file. Instead of serving the file, it downloads it, meaning that it does not read it as a php file.

More exactly it does not enter the fastcgi location ~ \.php$ directive.

Some interesting facts :

  • Everything works perfectly well for the admin bloc but not for the login block.
  • When I move the location ~ \.php$ directive above the login one and that I change ^~ /login into ~ /login, it works exept for the rewrite rule rewrite ^/login/(.+\.php)$ /$1 last;.

I did read the Wiki Nginx documentation on the topic so I am aware of the priorities in which nginx read the location directives but that does not tell me how to deal with this case! I also read

  • the similar question https://stackoverflow.com/questions/10126117/need-help-understanding-configuring-an-nginx-location-directive (unanswered)
  • https://stackoverflow.com/questions/11961323/howto-setup-window-nginx-virtual-directory-with-php-support that I tried to implement with no success
  • https://stackoverflow.com/questions/1011101/nginx-location-directive-doesnt-seem-to-be-working-am-i-missing-something that cover the case of a real (not virtual) subfolder.

Here is the config:

server {
 listen  80;

 server_name tyba-one.com *.tyba-one.com;
 root /var/www/tyba/public_html;
 rewrite_log on;
 error_page 404 /404.php;
 client_max_body_size 4M;

 if ($host ~* ^www\.(.*)){
  set $host_without_www $1;
  rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
 }

 location = / {
   rewrite ^/$ /index.php last;
 }

 location ^~ /login {
  rewrite ^(/login)$ $1/ permanent;
  rewrite ^/login/$ /login.php last;
  rewrite ^/login/(.+\.php)$ /$1 last;
 }    

 location ^~ /admin {
  rewrite ^(/admin)$ $1/ permanent;
  rewrite ^/admin/$ /page_builder.php last;
  rewrite ^/admin/(.+\.php)$ /$1 last;
 }

 location ~ \.php$ {
  try_files $uri =404;
  include /opt/nginx/conf/fastcgi_params;
  fastcgi_pass 127.0.0.1:9000;
  fastcgi_index index.php;
  fastcgi_param SCRIPT_FILENAME /var/www/tyba/public_html$fastcgi_script_name;
 }
}

I would like to understand what's going on and how to deal with such situations.


Solution 1:

nginx only processes one location block at each nesting level, and so /login.php is handled by the ^~ /login block and not the ~ \.php$ block. Since you only have rewrite statements in your location blocks, you actually don't need the location blocks at all (as long as the rewrite matches are specific enough, which yours are). Just move your rewrite statements into the root of the server block so that requests for /login and /admin still use the \.php$ location block:

rewrite ^/$ /index.php last;
rewrite ^(/login)$ $1/ permanent;
rewrite ^/login/$ /login.php last;
rewrite ^/login/(.+\.php)$ /$1 last;
rewrite ^(/admin)$ $1/ permanent;
rewrite ^/admin/$ /page_builder.php last;
rewrite ^/admin/(.+\.php)$ /$1 last;

location ~ \.php$ {
    ...
}