Назад | Перейти на главную страницу

Как настроить резервную страницу ошибки в nginx?

В настоящий момент я настраиваю nginx для обработки некоторых страниц ошибок и других мультимедийных файлов "по умолчанию" (таких как favicon.ico и robots.txt), и у меня возникла небольшая проблема, заставляющая все работать так, как я хочу, для определенных страниц ошибок. .

По сути, то, что я пытаюсь сделать, - это обслуживать определенные файлы для сервера в корневом каталоге этого сервера, например /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/. Если этот файл не существует, он не возвращается в каталог по умолчанию.

Во всяком случае, вы, вероятно, можете то, что я пытался выполнить (поэтому я включил первый рабочий пример).

Любые идеи?

Редактировать:

Основываясь на ответе Мартина Ф, я собрал вот что:

# Doesn't work when error page is returned on a POST request
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 и местоположений выше находится в файле server_defaults.conf, который включается в каждый виртуальный хост, поэтому я не жестко закодировал путь к каждому местоположению и использовал относительный путь для значений по умолчанию.

Изменить 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 should make it use the nginx-default 404 page.
    }
}

К сожалению, я опоздал с ответом на пару лет, но подумал, что это может помочь будущим поисковикам. Моя установленная версия Nginx - 1.2.4, и я создал следующий фрагмент конфигурации:

server {

server_name www.example.com
root /var/www/example


## Errors -> Locations
error_page   400 /400.html;
error_page   403 /403.html;
error_page   404 /404.html;
error_page   500 502 503 504 /50x.html;

## Locations -> Fallback
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;
}

## Fallback Directory
location @error {
    root /var/www/error;
}

}

Я обнаружил, что крайне важно включить "proxy_intercept_errors on;" в любом блоке местоположения, где также была включена error_page.

Без этой настройки блок местоположения будет перехватывать коды ошибок, возвращаемые восходящим потоком.

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors