Nginx-передать все 404 ошибки обратно в PHP-FPM для обработки пользовательских страниц ошибок
Я знаю, что это было задано тысячу раз, но все ответы, которые я нашел, просто не работают (для меня или обычно оригинального OP этих вопросов)... Поэтому я постараюсь объяснить проблему как можно лучше, и надеюсь, что мы сможем заставить ее работать на меня и на других, кто спрашивал раньше.
моя конфигурация Nginx (с большим количеством других ненужных вещей удалена) выглядит следующим образом:
http {
# Config from here removed
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
# Custom error pages
root /var/www/viovet_frontend;
error_page 404 = /error404.php;
# Any simple .php page
location ~ .php$ {
root /var/www/xxxxxx;
#index index.php index.html;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Lots more config and re-write rules here removed
}
upstream phpfastcgiservers {
server xxxxx1:9001;
server xxxxx2:9001;
server xxxxx3:9001;
fair;
}
}
все, что я пытаюсь сделать, это заставить Nginx поймать все 404s и отправить их обратно в PHP-FPM через location ~ .php$
для отображения пользовательской страницы ошибок, но я всегда получаю стандартную страницу ошибок Nginx.
следующие URL-адреса должны показывать выходные данные mydomain.co.uk/error404.php
:
- мидомен.co.uk / someNonExistantFile (не соответствует блокам местоположения)
- mydomain.co.uk/someMissingFile.php (соответствует .php файл расположение блока, но файл не существует)
но они на самом деле показывают стандартный Nginx 404 страница. Если location ~ .php$
возвращает другой код ошибки 404 (e.g 5xx) тогда мы не хотим участвовать, просто верните контент и заголовки, которые FastCGI вернул в первую очередь.
Я надеюсь, что имеет смысл и что кто-то может помочь. Заранее спасибо.
EDIT: я пробовал добавлять recursive_error_pages on;
в строке после # Custom error pages
но это на самом деле вызывает все Nginx 404 Not Found
ошибки, чтобы стать Nginx 500 Internal Server Error
ошибки.
EDIT: добавление других файлов: /и т. д./nginx/FastCGI-сервера.conf
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_params
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
Я думаю, что мне, вероятно, не нужны оба из них в любом случае! ;-)
5 ответов
я, наконец, понял большую часть этого. Спасибо всем за Ваши советы и время, чтобы написать ответ.
проблема в том, что наши error404.php
возвращал нашу страницу с ошибкой 404 не найден заголовок тоже (используя header('HTTP/1.0 404 Not Found');
) и Nginx затем перехватывал эту ошибку как recursive_error_pages
выключен (по умолчанию), и он показывал свою собственную страницу 404. Выключение fastcgi_intercept_errors
это решение. Если убрать header('HTTP/1.0 404 Not Found');
из файла ошибки, тогда мы получим ошибку, но с 200
что явно не то, чего мы хотим.
это, однако, не решит проблему доступа к отсутствующей странице, которая заканчивается .php
(таким образом, он соответствует блоку местоположения, поскольку мы теперь возвращаем стандартный ответ PHP-FPM на заголовок 404 с телом File not found.
. Я мог бы использовать ответ Нейта чтобы обойти это, но я бы предпочел не указывать все имена файлов там. Я буду искать другое решение для этого и опубликовать его здесь, когда я получу один.
EDIT: более полное решение:
вам нужно перехватить ошибки в вашем основном блоке местоположения php (fastcgi_intercept_errors
is on
), а затем еще один блок для ваших страниц ошибок, где вы их не перехватываете. См. этот пример конфигурации:
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
# Custom error pages
recursive_error_pages off;
error_page 404 = /http_errors/404.php;
# error_page 500 501 502 503 504 = /error5xx.php; # Not sure about this yet!
# Any simple .php page
location ~ \.php$ {
root /var/www/xxxxx;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Handling error pages
location ^~ /http_errors/ {
internal;
root /var/www/xxxxx;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors off;
}
}
это будет означать, что любая из ваших PHP-страниц, которые возвращают код состояния HTTP 404, будет иметь свой собственный контент (если таковой имеется) и содержимое вашего /http_errors/404.php
файл будет использоваться вместо.
Я считаю, что то, что вы просите, невозможно только с nginx - если вы не настроите все известные .php-файл вручную. Если вы можете перечислить известные .php файлы, вы можете обнаружить ожидаемый 404 на основе этой информации. Вместо того, чтобы захватить все .php файлы с регулярным выражением, вы указываете известные php файлы:
заменить location ~ \.php$ {}
примерно так:
местоположение ~ ^ / (index|foo|bar/admin / index).php$ {}
Это однако не захватите 404, сгенерированный вашим вне машины php-fpm, если запрос на предположительно известный php-файл, такой как .в PHP возвращает 404, хотя вы сказали nginx, что он должен существовать.
полное решение, вероятно, потребует дополнительного сервера перед ваш сервер nginx, который обнаруживает ответ 404 от php-fpm / nginx, который затем будет прокси другой запрос туда и обратно на ваш сервер для error404.в PHP. Вы все еще столкнетесь с проблемой вашего error404.в PHP файл также возвращает сам 404. Я заглянул в лак чтобы узнать, может ли обнаруженный 404 генерировать второй запрос на исходный сервер для страницы ошибки, но, к сожалению,vcl_backend_error может служить только 404 или повторить запрос. Лак - или что - то подобное-может иметь какой-то способ выполнить то, что вы хотите, но это будет нелегко.
все что я могу сказать, это одна из причин, почему большинство людей не настраивают nginx и php-fpm на разных машинах - это вызывает такие головные боли. Если возможно, вы действительно должны рассмотреть возможность сохранения nginx и php-fpm на одном компьютере и балансировки нагрузки на этих серверах. Какую бы пользу вы ни получали от их разделения, она, вероятно, не стоит дополнительных проблем.
на location ~ \.php$
блок требует try_files для проверки существования файла. Если не существует, верните 404 и ваш error404.php возьмет его.
http {
# Config from here removed
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
root /var/www/xxxxxx;
# Custom error pages
error_page 404 = /error404.php;
# Any simple .php page
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Lots more config and re-write rules here removed
}
upstream phpfastcgiservers {
server xxxxx1:9001;
server xxxxx2:9001;
server xxxxx3:9001;
fair;
}
}
ваш "root / var / www / xxxxxx;" должен быть за пределами "местонахождения ~ .php$ " блок и до "ошибки 404 = /error404.php;"
Если вы все еще не можете получить нужную страницу 404 из error404.php, я предлагаю вам начать отладку, используя стандартную копию nginx.conf, а затем настройте свой error_page оттуда, потому что то, что мы предложили, работает. Я использовал те же конфигурации для собственного сервера.
Если он все еще не работает, он должен проблема апстрима.
вы также хотите проверить свой
включить /и т. д./nginx/FastCGI-сервера.conf; включают fastcgi_params;
чтобы узнать, есть ли какие-либо переменные-изгои. Там могут быть дубликаты переменных.
общее эмпирическое правило при отладке. Снизить переменные. Начните с простой конфигурации и работать свой путь до пользовательских его.
правильно
error_page 404 /path/to/404.php;
Я знаю, что это работает, потому что я недавно создал приложение, и это была настройка для обработки ошибок. пожалуйста, обратите внимание, что я использую url rewriting to remove index.php
запросов для каждого каталога. Таким образом, вы можете настроить свой сценарий ошибок для регистрации информации в базе данных, что может быть полезно для сложной отладки ошибок ajax, среди прочего:
error_page 500 /error/?t=500;
error_page 501 /error/?t=501;
error_page 502 /error/?t=502;
error_page 503 /error/?t=503;
error_page 400 /error/?t=400;
error_page 401 /error/?t=401;
error_page 403 /error/?t=403;
error_page 404 /error/?t=404;
error_page 405 /error/?t=405;
error_page 406 /error/?t=406;
error_page 413 /error/?t=413;
error_page 414 /error/?t=414;
error_page 418 /error/?t=418; # i'm a teapot