Обработчик nginx 404 в php игнорирует статус HTTP

Это использует nginx 1.6.3 и PHP 7.0.7 через PHP-FPM в CentOS 7.2.

Я запустил много сайтов, использующих LAMP, и пытался переключиться на LEMP, но камнем преткновения, который продолжает возникать, является то, что мой обработчик страницы продолжает показывать 404 ошибки в статусе, даже если я установил разный статус в PHP. Это как если бы nginx полностью игнорировал заголовки, отправленные из PHP для страницы с ошибкой 404.

/etc/nginx/nginx.conf выглядит так:

user web web;
worker_processes auto;
error_log /var/web/Logs/WebServer/nginx-error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/web/Logs/WebServer/nginx-access.log  main;

    fastcgi_buffers 8 1024k;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

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

Конфигурация каждого домена выглядит так:

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;
        }
    }
}

Очень простой скрипт PHP есть (и да, я знаю, что заголовки избыточны, но все равно ничего не делает):

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

Я часами безуспешно искал, как это исправить. Я пробовал как минимум сотню различных форматов .conf, и ни один из них не работает. То, что у меня выше, по крайней мере, устанавливает REDIRECT_STATUS на 404, но я не нашел способа вернуть код состояния 200, если страница была найдена. Я не могу просто заставить nginx всегда возвращать 200, потому что на самом деле это может быть настоящий 404, поскольку реальный сценарий проверяет текущий URL в базе данных.

Как заставить nginx подчиняться заголовку статуса HTTP PHP?

0
задан 2 August 2016 в 23:20
3 ответа

Объединив уроки, которые я извлек из многих неудач, два других ответа, которые я получил (спасибо Майкл Хэмптон и Теро Килканен за то, что указали мне правильное направление), и предчувствие посмотреть дальше в try_files, я обнаружил, что проблема связана с тем, как try_files работает в моей установке. Здесь гораздо больше деталей: Как работает try_files? и тут: http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files

Окончательная рабочая конфигурация сервера:

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

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

    try_files $uri $uri/ @PageHandler;

    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 =404;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        include fastcgi.conf;
        fastcgi_param REDIRECT_STATUS 404;
    }
}

Как видите, я использую именованное расположение @PageHandler и завязывая это. Он использует HTTP-статус по умолчанию 200 вместо 404,но поскольку я могу управлять этим из PHP, я при необходимости явно установил его на 404.

Использование любой из следующих команд PHP изменяет статус, видимый моим браузером (все три не требуются):

http_response_code(404);
header("HTTP/1.1 404 Not Found");
header("Status: 404", true, 404);
0
ответ дан 4 December 2019 в 12:22

Мне эти вложенные блоки местоположения кажутся проблематичными, и они не нужны. Попробуйте следующее:

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

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

    try_files $uri $uri/ /PageHandler.php =404;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}
2
ответ дан 4 December 2019 в 12:22

Очевидно, что необходимо удалить это:

    error_page 404 /PageHandler;

Это полностью излишне, поскольку любой путь, который не найден как статический файл, будет направлен туда вашим первым try_files в любом случае. Необходимо или полезно использовать error_page только для обслуживания статических страниц ошибок.

1
ответ дан 4 December 2019 в 12:22

Теги

Похожие вопросы