guice666 guice666 - 4 months ago 7
PHP Question

Why does `/` in Nginx try_files break `~ \.php$`

I'm trying to figure out why the prepending

/
is not allowing the
\.php$
locations directive from picking up the script.

Below is a sample .conf I'm using for nginx. We're running API code, versioned out in path:
//domian.com/v#.#/endpoint/uri


Our document_root is one directory below the version number;
index.php
exists within the version directory:
path/to/sites/public/v1.0/index.php


index index.php # <-- this is in here globally
location ~ ^/(?<version>v[\d\.]+) {
try_files $uri $version/index.php?$args;
# Why does this NOT work? The / stopping \.php$ from matching
# try_files $uri /$version/index.php?$args;
}

location ~ \.php$ {

fastcgi_pass php56;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
[...]
}


I've tried all sorts of things, but can't seem to get this working. Once I remove the
/
it works as expected, but then my SCRIPT_FILENAME line changes from:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


To:

fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;


And this breaks direct PHP file calls -- something I don't want.

Answer

The first thing to note is that regex locations are evaluated in file order, so if /v1.1 matches the first location block, then /v1.1/index.php will also match the first location block. You seem to fix the problem in the wrong way by creating bad URIs with a missing leading /.

See this document for details.

You need to place your location ~ \.php$ block before your location ~ ^/(?<version>v[\d\.]+) block in order to allow .php files with the version prefix to be processed by the PHP block.