Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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?

share|improve this question
    
You could just rewrite ^ /index.php; instead of return 404; –  Martin Fjordvald Jan 5 '11 at 16:50
    
See my comment under tyoyengel's answer - I need some way of telling the index.php file to use error/404 as the path –  Richard Jan 5 '11 at 17:09

5 Answers 5

up vote 2 down vote accepted

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;
    }
}
share|improve this answer

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

share|improve this answer

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

error_page 404 /index.php

...if I read what you want correctly.

share|improve this answer
    
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 5 '11 at 16:56

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.

share|improve this answer
    
The if statement is to prevent a potential security hole described here: blog.martinfjordvald.com/2010/07/nginx-primer (linked from wiki.nginx.org/Configuration). It is one exception to the rule of not using if statements inside location blocks. –  Richard Jan 5 '11 at 16:20

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.