Nginx - как отключить перезапись для error_page

В настоящее время я размещаю несколько небольших статических веб-сайтов с использованием Nginx 1.10.2 на Fedora 25 Server Edition x86_64.

Я настроил Nginx так, чтобы он принимал .html для запросов без расширения файла ( try_files ), и для перенаправления (постоянная перезапись ) на версию URL без .html , если запрашивается . * \. html .

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

server {
    [...]

    try_files  $uri  $uri.html  $uri/index.html  =404;

    error_page  400  /errors/400.html;
    error_page  401  /errors/401.html;
    error_page  403  /errors/403.html;
    error_page  404  /errors/404.html;
    error_page  408  /errors/408.html;
    error_page  500  /errors/500.html;
    error_page  503  /errors/503.html;

    # Remove "index" from URL if requesting the front page.
    rewrite  "^/index(\.html)?$"    "/"    permanent;

    # Strip .html file extension, trailing slash, or "index.html".
    rewrite  "/(.+)(\.html|/|/index.html)$"  "/$1"  permanent;

    [...]
}

Вот что я думаю Nginx делает:

  1. клиентские запросы / поддельная страница
  2. поиск / поддельная страница , /fake-page.html или /fake-page/index.html .
  3. , когда ни один из них не соответствует, выполнить внутреннее перенаправление для отображения страницы с ошибкой 404.
  4. но затем /errors/404.html удаляется. флаг, вызывающий перенаправление пользователя 301.

Я пробовал несколько вариантов этой последней строки rewrite , даже помещая ее в место ^ ~ / errors / {} блок ( который, как я думаю, должен означать, что перезапись применяется только к URL-адресам, которые не являются в каталоге / errors /). Но все, что я сделал, привело к ошибке 404, постоянно перенаправляющей на страницу 404 , которая затем не возвращает фактический статус 404 --- или , он застревает в цикл перенаправления.

2
задан 13 February 2017 в 10:02
3 ответа

Я нашел более простое решение, вдохновленное ответом @ Anubioz.

server {
    [...]

    # This part's pretty common.
    # Assume ".html" or ".../index.html" if the original request doesn't
    # match any real files. Return error 404 if still can't find any
    # matching files.
    try_files  $uri  $uri.html  $uri/index.html  =404;

    # Match any resulting HTTP status codes with the custom error pages
    # that I designed.
    error_page  400  /errors/400.html;
    error_page  401  /errors/401.html;
    error_page  403  /errors/403.html;
    error_page  404  /errors/404.html;
    error_page  408  /errors/408.html;
    error_page  500  /errors/500.html;
    error_page  503  /errors/503.html;

    # Make sure the paths to the custom error pages are not transformed
    # before sending the actual status codes to a request.
    # These error pages are for *internal* use only.
    location = "/errors/400.html" {
        internal;
    }
    location = "/errors/401.html" {
        internal;
    }
    location = "/errors/403.html" {
        internal;
    }
    location = "/errors/404.html" {
        internal;
    }
    location = "/errors/408.html" {
        internal;
    }
    location = "/errors/500.html" {
        internal;
    }
    location = "/errors/503.html" {
        internal;
    }

    # Remove "index" from URL if requesting the front page.
    location ~ "^/index(\.html)?$" {
        return  301  "/";
    }

    # Strip .html file extension, trailing slash, or index,
    # forcing the "pretty" URL, if user requests a ".html" URL.
    location ~ "^/(.+)(\.html|/|/index|/index.html)$" {
        return  301  "/$1";
    }

    [...]
}

Блоки location , содержащие внутренние директивы , сохраняют страницы ошибок от прикосновения к обычной обработке URL. Я пытался сопоставить только каталог / errors / , поэтому мне не пришлось бы повторять внутреннюю директиву снова и снова, но Nginx сопоставляет входящие запросы для перезаписи правил, в основном сортируя по специфичности селектор правил: только точные совпадения с каждой настраиваемой страницей ошибок имели достаточную специфичность, чтобы выявить страницы с ошибками до того, как Nginx сможет запустить на них процесс перезаписи URL.

мне кажется, что происходит. И эта конфигурация делает именно то, что говорится в комментариях к коду, чего я хотел с самого начала.)

0
ответ дан 3 December 2019 в 12:37

Я бы посоветовал вам обернуть перезаписи внутри блоков местоположения , иначе будет сложно контролировать их глобальный охват.

Этот пример, кажется работайте с фрагментом, который вы опубликовали в своем вопросе:

server {
    root /path/to/root;

    location / {
        # Remove "index" from URL if requesting the front page.
        rewrite  "^/index(\.html)?$"    "/"    permanent;

        # Strip .html file extension, trailing slash, or "index.html".
        rewrite  "/(.+)(\.html|/|/index.html)$"  "/$1"  permanent;

        try_files  $uri  $uri.html  $uri/index.html  =404;
    }

    error_page  400  /errors/400.html;
    error_page  401  /errors/401.html;
    error_page  403  /errors/403.html;
    error_page  404  /errors/404.html;
    error_page  408  /errors/408.html;
    error_page  500  /errors/500.html;
    error_page  503  /errors/503.html;

    location /errors/ {
    }
}
1
ответ дан 3 December 2019 в 12:37

Это был крепкий орешек, но в итоге он работает как запрошено:

server {

    [...]

    root /path/to/root;
    set $docroot "/path/to/root";
    error_page  400  /errors/400.html;
    error_page  401  /errors/401.html;
    error_page  403  /errors/403.html;
    error_page  404  /errors/404.html;
    error_page  408  /errors/408.html;
    error_page  500  /errors/500.html;
    error_page  503  /errors/503.html;

    location = /errors/404.html {
        root $docroot;
        internal;
    }

    location ~ ^/index(\.html)?$
    {
        return 301 "/";
        break;   
    }

     location ~ ^/$
    {
        try_files  $uri  $uri.html  $uri/index.html  =404;
        break;
    }

    location ~ ^/(.+)(\.html|/|/index.html)$
    {
        if (-f $docroot/$1) {
            return 301  "/$1";
            break;
        }

        if (-f $docroot/$1.html) {
            return 301  "/$1";
            break;
        }

        if (-f $docroot/$1/index.html) {
            return 301  "/$1";
            break;
        }

        try_files missing_file  =404; 
    }

    location ~ ^/(.+)(?!(\.html|/|/index.html))$
    {
        try_files  $uri  $uri.html  $uri/index.html  =404;    
    }

    [...]
}

Попробую дополнить это комментариями чуть позже;)

0
ответ дан 3 December 2019 в 12:37

Теги

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