В настоящее время я размещаю несколько небольших статических веб-сайтов с использованием 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 делает:
/ поддельная страница
/ поддельная страница
, /fake-page.html
или /fake-page/index.html
. /errors/404.html
удаляется.
флаг, вызывающий перенаправление пользователя 301. Я пробовал несколько вариантов этой последней строки rewrite
, даже помещая ее в место ^ ~ / errors / {}
блок ( который, как я думаю, должен означать, что перезапись применяется только к URL-адресам, которые не являются в каталоге / errors /). Но все, что я сделал, привело к ошибке 404, постоянно перенаправляющей на страницу 404 , которая затем не возвращает фактический статус 404 --- или , он застревает в цикл перенаправления.
Я нашел более простое решение, вдохновленное ответом @ 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.
мне кажется, что происходит. И эта конфигурация делает именно то, что говорится в комментариях к коду, чего я хотел с самого начала.)
Я бы посоветовал вам обернуть перезаписи
внутри блоков местоположения
, иначе будет сложно контролировать их глобальный охват.
Этот пример, кажется работайте с фрагментом, который вы опубликовали в своем вопросе:
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/ {
}
}
Это был крепкий орешек, но в итоге он работает как запрошено:
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;
}
[...]
}
Попробую дополнить это комментариями чуть позже;)