Вопрос или проблема
Я настраиваю обработку некоторых страниц ошибок и других “стандартных” медиафайлов (таких как favicon.ico и robots.txt) в nginx на данный момент, и столкнулся с небольшой проблемой в том, чтобы всё работало так, как я хочу для определенных страниц ошибок.
В основном, я пытаюсь предоставить определенные файлы для сервера под корнем этого сервера, например, /var/www/someserver.com/robots.txt. Если этот файл не существует, я хочу, чтобы nginx переходил к “по умолчанию”, т.е. /var/www/default/robots.txt. Это основной смысл того, как я это (успешно) настроил:
server {
...
root /var/www/someserver.com;
location ~* ^/(robots\.txt)$ {
error_page 404 = @default;
}
location @default {
root /var/www/default;
}
}
Это работает отлично.
Я пытаюсь сделать то же самое для страниц ошибок, но не могу этого достичь:
server {
...
root /var/www/someserver.com;
error_page 404 /404.html;
location ~* ^/(404\.html)$ {
error_page 404 = @default;
}
location @default {
root /var/www/default;
}
}
Обратите внимание, что это “работает” в том смысле, что если вы посетите someserver.com/404.html, он сначала попытается загрузить /var/www/someserver.com/404.html, а затем перейдёт к /var/www/default/404.html, если это не будет найдено. Однако, если вы посетите someserver.com/blahblah, он показывает страницу 404 только если она установлена в /var/www/someserver.com/. Он не переходит к каталогу по умолчанию, если этот файл не существует.
Тем не менее, вы, вероятно, понимаете, что я пытался достичь этого (вот почему я включил первый рабочий пример).
Есть идеи?
Редактирование:
Исходя из ответа Мартина Ф, вот что я в итоге собрал вместе:
# Не работает, когда страница ошибки возвращается на POST-запрос
server {
...
root /var/www/someserver.com;
error_page 404 = @notfound;
error_page 500 502 504 = @server_error;
error_page 503 = @maintenance;
location @notfound {
try_files /404.html /../default/404.html =404;
}
location @server_error {
try_files /500.html /../default/500.html =500;
}
location @maintenance {
try_files /503.html /../default/503.html =503;
}
}
Это работает отлично. Фактический блок error_pages и locations выше находится в файле server_defaults.conf, который включается в каждый виртуальный хост, вот почему я не закодировал путь в каждый location и использовал относительный путь для значений по умолчанию.
Редактирование 2:
Этот подход имеет проблему. Если вы отправляете POST на URL, который возвращает ошибку, метод запроса POST отправляется с попытками try_files. Это (для меня) приводит к ошибке 405 Not Allowed, потому что nginx по сути пытается сделать POST на, например, /default/500.html вместо того, чтобы просто получить эту страницу.
Редактирование 3:
Я опубликовал решение, которое работает и гораздо ближе к моей первоначальной идее.
В итоге я пошёл с чем-то гораздо ближе к моей первоначальной идее. Ключом, который мне не хватало, оказалось направление recursive_error_pages
. Всё, что мне действительно нужно было сделать, это включить это “включить”, и моя первоначальная идея сработала. Вот как выглядит соответствующая часть моего конфигурационного файла сейчас:
server {
...
root /var/www/someserver.com/;
error_page 400 404 /404.html;
error_page 500 502 504 /500.html;
error_page 503 /503.html;
recursive_error_pages on;
location ~* ^/(404\.html|500\.html|503\.html)$ {
log_not_found off;
error_page 404 = @default;
}
location @default {
log_not_found on;
root /var/www/default;
}
}
Я включил другие типы ошибок, которые не входили в мой первоначальный вопрос, потому что это и вызвало у меня трудности с подходом Мартина Ф, который в остальном был отличным. Директива log_not_found
просто обеспечивает то, что у меня нет 404 в моём журнале, когда страница ошибки не найдена в исходном корне.
try_files — это правильный подход здесь. Следующая конфигурация должна сработать, но я не проверял её на наличие ошибок синтаксиса.
server {
...
root /var/www;
location / {
try_files /someserver.com$uri /default$uri /someserver.com$uri/ /default$uri/ @notfound;
}
location @notfound {
try_files /someserver/404.html /default/404.html =404; # =404 должно заставить использовать стандартную страницу 404 nginx.
}
}
К сожалению, я немного запоздал с моим ответом, но я думал, что это может помочь будущим искателям. Моя установленная версия Nginx — 1.2.4, и я создал следующий фрагмент конфигурации:
server {
server_name www.example.com
root /var/www/example
## Ошибки -> Локации
error_page 400 /400.html;
error_page 403 /403.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
## Локации -> Резервное копирование
location = /400.html {
try_files /400.html @error;
internal;
}
location = /403.html {
try_files /403.html @error;
internal;
}
location = /404.html {
try_files /404.html @error;
internal;
}
location = /50x.html {
try_files /50x.html @error;
internal;
}
## Директория резервного копирования
location @error {
root /var/www/error;
}
}
Я обнаружил, что крайне важно включить “proxy_intercept_errors on;” в любом блоке локации, где также включена ошибка_page.
Без этой настройки блок локации будет перехватывать коды ошибок, возвращающиеся от upstream.
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
Вот как вы можете обойти проблему “405 Not Allowed”. Что-то вроде этого:
http {
map $request_method $x_static_content_denied {
default 1;
GET 0;
HEAD 0;
}
# ...
server {
# ...
error_page 500 502 504 = @server_error;
# ...
location @server_error {
if ($x_static_content_denied) { return 500; }
try_files /500.html /../default/500.html =500;
}
}
}
Он возвращает стандартную страницу ошибки nginx в случае, если статическое содержимое не разрешено.
Ответ или решение
Настройка страницы ошибок с резервным копированием в Nginx
Настройка серверов Nginx для обработки страниц ошибок играет ключевую роль в создании качественного пользовательского опыта. В данной статье мы подробно рассмотрим, как настроить резервные страницы ошибок и файлов, таких как robots.txt
и категории ошибок, чтобы при отсутствии страницы в основном каталоге был доступен запасной вариант.
Основная концепция
Для начала, необходимо понимать, что в Nginx можно настроить обработку ошибок, используя директивы error_page
и try_files
. Эти инструменты позволяют вам отправлять пользователя на определенные страницы ошибок, а также на страницы, которые служат резервом.
Пример конфигурации
Ниже приведен пример конфигурации Nginx, который иллюстрирует, как настроить резервирование:
server {
listen 80;
server_name someserver.com;
root /var/www/someserver.com;
# Обрабатываем различные коды ошибок
error_page 400 404 /404.html;
error_page 500 502 504 /500.html;
error_page 503 /503.html;
# Включаем рекурсивную обработку ошибок для страниц
recursive_error_pages on;
# Локация для обработки поиска ошибок 404
location = /404.html {
try_files /404.html @default;
internal;
}
# Локация для обработки поиска ошибок 500
location = /500.html {
try_files /500.html @default;
internal;
}
# Локация для обработки резервных страниц
location @default {
root /var/www/default;
try_files /404.html /500.html =404;
}
}
Пояснение конфигурации
-
Директивы error_page: Используются для указания пользовательских страниц ошибок, которые будут отображаться при возникновении определённых ошибок, таких как 404 (Не найдено) или 500 (Внутренняя ошибка сервера).
-
recursive_error_pages: Включение этой директивы позволяет Nginx рекурсивно обрабатывать страницы ошибок, что означает, что если указанная страница ошибки (например,
404.html
) не найдена, то будет использоваться резервная, указанный в директории, в данном случае/var/www/default
. -
Локации для обработки: В конфигурации предусмотрены специальные локации, которые обрабатывают запросы к страницам ошибок. Если пользователь запрашивает страницу ошибки прямым запросом, то сначала проверяется наличие файла в основном каталоге. Если файл отсутствует, управление передается к резервной локации (
@default
). -
Использование try_files: Эта директива позволяет проверять наличие файлов в указанном порядке. В случае, если первый файл не найден, проверяется следующий.
Основные проблемы и их решения
1. Ошибка "405 Not Allowed"
Проблема может возникнуть, если пользователь сталкивается с кодом ошибки из-за метода POST. В этом случае обратите внимание на директиву proxy_intercept_errors
, которая должна быть включена в конфигурации:
location @server_error {
proxy_intercept_errors on;
try_files /500.html /../default/500.html =500;
}
Это обеспечит корректное поведение сервера, избегая ошибок при обработке POST-запросов.
2. Логирование ошибок
Используйте директиву log_not_found
для минимизации запретов в логах, если файла ошибки не существует в основном каталоге:
location ~* ^/(404\.html|500\.html|503\.html)$ {
log_not_found off;
error_page 404 = @default;
}
Заключение
Правильная настройка страницы ошибок с резервным вариантом в Nginx – это важный шаг к обеспечению высокого уровня пользовательского опыта. Используя приведенные выше рекомендации и настройки, вы сможете настроить надежный механизм обработки ошибок, который улучшит взаимодействие пользователей с вашим сайтом.
SEO-оптимизация
Для улучшения видимости вашей конфигурации в поисковых системах, исходя из ключевых слов, таких как "настройка Nginx", "страницы ошибок Nginx", "резервные страницы" и "обработка ошибок Nginx", вы можете рассмотреть возможность добавления дополнительных материалов или часто задаваемых вопросов, касающихся этой темы.