8

I have the following nginx vhost config:

server {
    listen 80 default_server;

    access_log /path/to/site/dir/logs/access.log;
    error_log /path/to/site/dir/logs/error.log;

    root /path/to/site/dir/webroot;
    index index.php index.html;

    try_files $uri /index.php;

    location ~ \.php$ {
            if (!-f $request_filename) {
                    return 404;
            }

            fastcgi_pass localhost:9000;
            fastcgi_param SCRIPT_FILENAME /path/to/site/dir/webroot$fastcgi_script_name;
            include /path/to/nginx/conf/fastcgi_params;
    }
}

I want to redirect all requests that don't match files which exist to index.php. This works fine for most URIs at the moment, for example:

example.com/asd
example.com/asd/123/1.txt

Neither of asd or asd/123/1.txt exist so they get redirected to index.php and that works fine. However, if I put in the url example.com/asd.php, it tries to look for asd.php and when it can't find it, it returns 404 instead of sending the request to index.php.

Is there a way to get asd.php to be also sent to index.php if asd.php doesn't exist?

Richard
  • 836
  • 2
  • 8
  • 21

7 Answers7

12

Going by your additional comments this sounds like it might be the most optimal way, though it's not a pretty config.

server {
    listen 80 default_server;

    access_log /path/to/site/dir/logs/access.log;
    error_log /path/to/site/dir/logs/error.log;

    root /path/to/site/dir/webroot;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        try_files $uri @missing;

        fastcgi_pass localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /path/to/nginx/conf/fastcgi_params;
    }

    location @missing {
        rewrite ^ /error/404 break;

        fastcgi_pass localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
        include /path/to/nginx/conf/fastcgi_params;
    }
}
Martin Fjordvald
  • 7,749
  • 1
  • 30
  • 35
5

Wow, I think all you want to replace that code is:

error_page 404 /index.php

...if I read what you want correctly.

  • This works well, and so I have `error_page 404 /error/404/` which then redirects to `index.php`, but then in the php request_uri (what I use to get the path requested) it has `asd.php` (assuming this is what was typed in and resulted in the 404) and I have no way of getting the `error/404` path to then act on in the php. Is there any way to pass this path to php? I.E. I still want a single front index.php to handle errors as well. How do I tell the index.php that this is an error to handle? – Richard Jan 05 '11 at 16:56
2

What you are trying to do is same as custom error page. You can use the error_page property of nginx to achieve this. Follow the link for more information

http://wiki.nginx.org/HttpCoreModule#error_page

Sameer
  • 4,118
  • 2
  • 17
  • 11
2

It's worked with me!

    location /anyfolder {
        error_page 404 /yourhandler.php?fnf=$uri;
    } 
Trieu Ngo
  • 21
  • 2
1

I think the problem is that you are using "try_files" along with an "if" statement in your location. From the documentation, try_files is supposed to be a replacement for if and mod_rewrite style existence check. From the nginx wiki, the "try_files" page ( http://wiki.nginx.org/HttpCoreModule#try_files ):

"try_files is basically a replacement for the typical mod_rewrite style file/directory existence check. It is supposed to be more efficient than using if - see IfIsEvil"

Check the "if" wiki page ( http://wiki.nginx.org/NginxHttpRewriteModule#if ):

"note: Before using if please see the if is evil page and consider using try_files instead."

So, try remove that if check and just staying with the "try_files". That should check for the existence of any page (including asd.php or anything else endind in .php) and fall back to index.php if it doesn't find it.

danakim
  • 392
  • 2
  • 9
  • The if statement is to prevent a potential security hole described here: http://blog.martinfjordvald.com/2010/07/nginx-primer/ (linked from http://wiki.nginx.org/Configuration). It is one exception to the rule of not using if statements inside location blocks. – Richard Jan 05 '11 at 16:20
0

Richard, according to the Pitfalls guide its recommended to set “cgi.fix_pathinfo = 0″ in php.ini as it resolves a potential vulnerability between nginx and php.

Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
Roger
  • 473
  • 11
  • 22
0

I want to redirect all missing php files to custom internal /error404 error page. I will post my solution found during permutation.

error_page 404 /error404;

didn't help me. Neither did combinations of location, @missing, rewrite and break. But

location ~ \.php$ {
    # this is it! $fastcgi_script_name points to my url
    try_files $fastcgi_script_name = /error404; 
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
    ...
    etc.
vladkras
  • 171
  • 1
  • 7