Nginx, PHP FPM, try_files and path_info

Nginx, PHP FPM, try_files and path_info

In the post, http://wiki.nginx.org/PHPFcgiExample, the author gives an URL example for testing various parameters, especially PATH_INFO and $fastcgi_path_info.

This URL is, http://lemp.test/test.php/foo/bar.php?v=1 (this URL is not a hyperlink and does not work, of course)

I was interested to find what Location clause would be necessary to test this on my own server.

In my case, I wanted to test in a separate sub-directory, so the test string becomes:-

http://mydomain.co.uk/mytest/test.php/foo/bar.php?v=1 (this URL does not work either. It’s intended you construct a test on your own server)

As the article says, the test.php file is:-

<pre>
    <?php
        var_export($_SERVER)
    ?>
</pre>

I’m the type of person that fears Regex. I don’t know why, but with a lot of patience and a late night, I’ve got this:-

location ~* ^/mytest/(.+\.php)(/.*)?$

and the steps are:-

“~*” the nginx command for case insensitive matching.
”^/mytest/” the sub-directory off the site’s root where the test.php file is present.
”(.+\.php)” the regex specification that will match one or more characters before the .php extension of the filename, where \. escapes the dot. This protects against a file, “.php” being processed.
“(/.*)?” the regex specification that will match zero or more characters after a slash, where the ? makes this optional.
”$” and finally the $ marks the end of the string. Note that the “?v=1” is never considered by the location matching.

If you think that two php filenames in the URL is a bit odd, various authors suggest it’s a possible construct and give OwnCloud as an example (I’ve not investigated this).

Now we have got the Location sorted, we need to consider whether try_files being included in the location block where fastcgi_split_path_info is also used.
It would appear there is a bug/feature, that PATH_INFO will not be correct if both are present.
And it’s true – I’m using version 1.8.0 when writing this.
Seems it won’t be fixed – see http://trac.nginx.org/nginx/ticket/321

My complete but minimalistic Location block I’ve used to test and correct the issue is as follows:-

    #At least one char before the .php, then an optional / with 0 or more chars after
    location ~* ^/mytest/(.+\.php)(/.*)?$
    {       
        index index.php;       
        try_files $uri $uri/ /mytest/index.php$args; #You can comment this out, and PATH_INFO will be same
        include fastcgi_params; #Put here first so we can override
        fastcgi_split_path_info ^(.+\.php)(/.*)$; #Slightly different from others, and matches my Location regex command
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        set $real_script_name $fastcgi_script_name;
        if ($document_uri ~* “^(.+?\.php)(/.*)$”) #Note using $document_uri as this avoids including the query string in the test
        {
            set $real_script_name $1;
            set $path_info $2;
        }
        fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
        fastcgi_param SCRIPT_NAME $real_script_name;
        fastcgi_param PATH_INFO $path_info;
        #Check to see if the file does really exist
        if (!-f $document_root$real_script_name)
        {
            return 404;
        }
    }

Comments are closed.