简体   繁体   中英

Nginx rewrite rule to PHP that also allows .php in the URI

Slightly unusual question, hopefully with a simple answer! (I'm new to Nginx)

I have an old PHP system running on Apache and I'd like to bring it over to Nginx, but my issue is that some of it needs to be rewritten back to a single handler file ( /handler.php ) and some of it wants to execute the actual files. The tricky part seems to be that almost all routes end in .php whether they reference an actual PHP file or not.

For example, /foo.php might be an actual file that executes its own code, but /bar.php might not exist and therefore wants to call /handler.php . There are also instances of routes of the form /bar (without the .php extension) that also want to call /handler.php .

There are lots of all types in the system (far, far more than I'd like to manually code for). Is there a solution to this in Nginx?

The server block currently contains something like:

location / {
    try_files $uri $uri/ /handler.php$is_args$args;
}

include /etc/nginx/sites.d/*.conf;

and sites.d/php.conf currently looks something like:

location ~ \.php$
{
    fastcgi_pass    unix:/var/run/php5-fpm.sock;
    fastcgi_index   index.php;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;

    include         /etc/nginx/fastcgi_params;
}

But this treats all routes with .php extensions as actual files and just gives me the standard "No input file specified." error for any that don't exist (performs no rewrite). No problem if there is no .php extension, they call /handler.php without issue.

So in summary, with this almost default setup:

/foo.php - works (actual file)
/bar.php - fails (no file)
/bar     - works (no file)

If I only had the "no-file" type I could update the php.conf to something like "location ~ \\handler.php$" , but in this case it means all actual .php files just trigger a download (ie /foo.php fails).

Any help is appreciated! Thanks in advance.

In your location block matching .php You can test if the file actually exists and redirect to handler.php if it's not there:

location ~ \.php$ {
    if (!-f $request_filename) {
        rewrite ^.*\.php$ /handler.php last;
    }

    fastcgi_pass    unix:/var/run/php5-fpm.sock;
    fastcgi_index   index.php;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;

    include         /etc/nginx/fastcgi_params;
}

Updated example

Alternative location rule using try_files (as suggested by OP):

location ~ \.php$ {
    try_files $uri /handler.php$is_args$args;

    fastcgi_pass    unix:/var/run/php5-fpm.sock;
    fastcgi_index   index.php;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;

    include         /etc/nginx/fastcgi_params;
}

With the first version using rewrite you can do substitution from regex matches. But try_file I think is the recommended method of testing for file existence. Thank you to the OP for suggesting an improved alternative.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM