nginx 404 handler in php ignores HTTP status

Mark Ormston asked:

This is using nginx 1.6.3 and PHP 7.0.7 via PHP-FPM in CentOS 7.2.

I have run many sites using LAMP and have been trying to switch to LEMP, but a sticking point that keeps coming up is that my page handler keeps showing 404 errors in the status, even though I have set a different status in PHP. It is as if nginx is completely ignoring the headers sent from PHP for the 404 error page.

My server configuration is:

server {
    listen       80;
    server_name  www.something.com;

    root /var/web/www.something.com/;
    index index.php index.html;

    error_page 404 /PageHandler;

    location / {
        try_files $uri $uri/ /PageHandler =404;
        location ~ .php$ {
            try_files $uri =404;
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            include fastcgi.conf;
        }
        location /PageHandler {
            try_files /PageHandler.php =500;
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            include fastcgi.conf;
            fastcgi_param REDIRECT_STATUS 404;
        }
    }
}

The very simple PHP script is (and yes, I know the headers are redundant, and still it does nothing):

<?php
  http_response_code(200);
  header("HTTP/1.1 200 OK");
  header("Status: 200", true, 200);
?>
Test <?= $_SERVER["REQUEST_URI"] ?>, code <?= $_SERVER["REDIRECT_STATUS"] ?>

I have searched fruitlessly for hours on how to fix this. I have tried at least a hundred different .conf formats, and none of them work. What I have above at least sets REDIRECT_STATUS to 404, but I have found no way to be able to return a 200 status code if a page was found. I cannot just have nginx always return a 200, because it may actually be a genuine 404 since the actual script tests the current URL in a database.

How do I get nginx to obey PHP’s HTTP status header?

My answer:


The obvious thing to do is to remove this:

    error_page 404 /PageHandler;

It’s completely redundant, since any path that isn’t found as a static file will be directed there by your first try_files anyway. It’s only necessary or useful to use error_page to serve static error pages.


View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.