0

Unlike other questions related to nginx not executing PHP files, mine does, the problem comes when I use SEO like urls instead and redirect to a php script, then instead of executing the code it sends the script as plain text to the browser.

Basically what I want is that every request send to the HTTP server for which there's no an actual file, index.php script will be executed and its output returned to the browser. But what is happening is that I'm getting the code inside index.php instead.

This is the section of my configuration file where the redirection is done. It's been actually translated from a former Apache's .htaccess file:

    location / {
        if (!-e $request_filename){
            rewrite ^(.*)$ /index.php break;
        }
    }

These are the PHP related directives, actually these are before the previous one in the configuration file:

    location ~ \.php$ {
        try_files /dd05cf208ebd3d4559f3af75016a1e3d.htm @php;
    }

    location @php {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass unix:/var/lib/php7.0-fpm/web4.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors on;
    }

I've been using Apache with mod_php for decades and the equivalent directives just worked out of the box, but I'm new with Nginx and I don't know where to start debugging this.

  • So basically you want to redirect every 404 to an index.php? You can set something like this "error_page 404 /index.php;" – Federico Galli Jun 21 '17 at 13:29
1

The correct way to implement front-controller pattern in nginx is the following:

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

Your PHP location blocks look a bit odd. I guess that your objective with the configuration is to enable nginx to show a maintenance notice in /dd05cf208ebd3d4559f3af75016a1e3d.htm if the file exists.

This configuration looks correct to me, except that the try_files inside your @php block makes requests fail, since it makes nginx look for files with names specified in the URI, and with friendly URLs those files simply do not exist.

There is no reason to include that, so your PHP configuration should look like the following.

location ~ \.php$ {
    try_files /dd05cf208ebd3d4559f3af75016a1e3d.htm @php;
}

location @php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/var/lib/php7.0-fpm/web4.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
}
| improve this answer | |
0

Your SEO solution is using non-recommended if directive inside location. If Is Evil:

Directive if has problems when used in location context, in some cases it doesn’t do what you expect but something completely different instead. In some cases it even segfaults. It’s generally a good idea to avoid it if possible.

The correct way to achieve what I believe you want would be try_files, e.g.:

location / {
    try_files $uri $uri/ @missing;
}

location @missing {
    rewrite ^(.*)$ /index.php break;
}
| improve this answer | |
  • 1
    If you want to go with the rewrite way, you can use rewrite ^ /index.php break;, it does the same as ^(.*)$. I don't know if that makes any real difference performance-wise though. At least there is no variable created... – Tero Kilkanen Jun 21 '17 at 13:57
  • Your answer is the most straight-forward way of doing this. This only keeps the flexibility, if more complex rewrite pattern is required later, or if a redirect is needed instead. But as we shouldn't predict that, I'll upvote for your answer. – Esa Jokinen Jun 21 '17 at 14:10
0

Into the server location put

error_page 404 =200 /index.php;

to redirect all 404 (not found) pages to your index.php

You don't need all the rewrite and location stuff, if you just want to catch all missing pages.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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