Як налаштувати сторінку резервної помилки в nginx?


10

Наразі я налаштовую обробку 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;
    }
}

Це працює приголомшливо. Фактичний блок помилок_сторінок та локацій вище знаходиться у файлі server_defaults.conf, який входить до кожного віртуального хоста, тому я не важко кодував шлях до кожного місця та використовував відносний шлях для значень за замовчуванням.

Редагувати 2:

Такий підхід має проблему. Якщо ви відправляєте POST на URL-адресу, яка повертає помилку, метод запиту POST надсилається із спробами try_files. Це (для мене) призводить до 405 не дозволених помилок, оскільки nginx по суті намагається POST, наприклад, /default/500.html, а не просто отримує цю сторінку.

Редагувати 3:

Я розмістив рішення, яке працює набагато ближче до моєї оригінальної ідеї.

Відповіді:


10

Я закінчив щось із наближеною до моєї оригінальної ідеї. Ключовим, який я бракував, виявилася директива 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 - журналі , коли сторінка помилки не знайдений в вихідному корені.


Це спрацьовує вкрай (наприклад, комбінація 404 / POST), але, схоже, проковтне код помилки HTTP і надсилає 200 ... Чи маєте ви таку поведінку, як і я?
Жовтень

2
Ви можете видалити log_not_found off;та додати internal;замість цього.
Алікс Аксель

Проблема, яку ви помітили у запиті POST, що спричинила помилку, - дивна поведінка nginx, див. Trac.nginx.org/nginx/ticket/824
Robo

5

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

Так, саме це мені було потрібно. Я намагався використовувати try_files, але ваша відповідь дала мені зрозуміти, що мені потрібно створити спеціальне внутрішнє місце для цього. Я відредагував свою відповідь, щоб показати конфігурацію, яка працювала на мене, яка має кілька перетворень на те, що ви запропонували.
Джим Д

Дивіться мою редакцію 2 вище. Як я можу сказати, ця пропозиція не працює з POST-запитами. Оскільки try_files використовує метод запиту оригінального запиту, ви отримуєте відповідь 405 Not Allowed.
Джим Д

@JimD: Ну, ви точно не використовуєте цей підхід, ви використовуєте модифікований. Це працює для мене. Спробуйте оновити бінарний файл Nginx, якщо він старший 0,8.x
Мартін Фьордвальд,

Ну, проблема полягає в тому, що я використовую це більше, ніж просто 404, тому я маю робити помилку_файли -> місце розташування -> пробні_файли замість розташування -> спробувати_файли -> місцезнаходження -> спробувати_файли, як ти є. Однак я перебуваю на 0.7.x бінарному від пакета, тому спробую створити його з джерела і побачити, чи це вирішує це.
Джим Д

2

На жаль, я запізнився на пару років зі своєю відповіддю, але я подумав, що це може допомогти майбутнім шукачам. У мене встановлена ​​версія 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;
}

}

1
Гарне використання internal.
Клінт Пахл

0

Я виявив, що важливо включити "proxy_intercept_errors on"; " у будь-якому блоці локації, де також була включена сторінка помилок.

Без цього параметра блок розташування перехопить коди помилок, що повертаються з висхідного потоку.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.