Удаление index.html и.html из URL с помощью nginx
Моя основная цель - предоставить nginx следующие чистые URL:
/
служит/index.html
/abc/
служит/abc/index.html
/abc/def
служит/abc/def.html
/abc
перенаправляет на/abc/
Чтобы иметь канонические имена для каждого ресурса, я также хочу нормализовать любой URL с избыточными именами файлов или расширениями:
/index.html
перенаправляет на/
/abc/index.html
перенаправляет на/abc/
/abc/def.html
перенаправляет на/abc/def
Директивы, которые, как я думал, могли бы сделать это:
index index.html;
try_files $uri.html $uri $uri/ =404;
# Redirect */index and */index.html to *.
rewrite ^(.*)/index(\.html)?$ $1 permanent;
# Redirect *.html to *.
rewrite ^(.+)\.html$ $1 permanent;
Тем не менее, результат этого отличается от того, что я ожидал:
/
,/index
а также/index.html
все перенаправить на/
(Цикл)./abc
а также/abc/
оба перенаправить на/abc/
(Цикл).
(Работает так, как /abc/def.html
а также /abc/def
; не работают только URL-адреса каталогов.)
Я не уверен, что здесь происходит; может быть, я неправильно понимаю, как rewrite
работает?
(Я уже пытался использовать блоки местоположения вместо этого, но это также приводит к появлению петель try_files
выполняет внутреннее перенаправление в блок местоположения, который отправляет HTTP 301.)
Редактировать: По сути, мне нужно что-то вроде блока местоположения, который соответствует только исходному URI запроса, но игнорируется для внутренних перенаправлений, поэтому он не создает цикл в сочетании с директивой try_files.
2 ответа
Возможно, вы ищете решение, подобное тому, которое описано здесь:
server {
listen 80;
server_name mysite.com;
index index.html;
root /var/www/mysite/public;
location / {
try_files $uri $uri/ @htmlext;
}
location ~ \.html$ {
try_files $uri =404;
}
location @htmlext {
rewrite ^(.*)$ $1.html last;
}
}
Я полагаю, что нашел решение, хотя у меня недостаточно опыта, чтобы сказать, может ли оно сломаться в особых случаях или может быть легче решено другим способом.
По сути, проблема в том, что location ~ ... {}
блок сопоставляется не только с исходным URI запроса, но и с результатом try_files
и другие переписывает. Так что, если у меня есть блок местоположения для удаления index.html или.html с перенаправлением, то он будет работать не только при запросе клиента index.html
или же abc.html
напрямую, но также, если клиент запрашивает /
или же abc
и сервер внутренне перенаправляет их в /index.html
а также abc.html
соответственно, вызывая цикл перенаправления.
Тем не менее, модуль перенаправления обеспечивает if
директива, которая может проверить $request_uri
переменная - это остается неизменным внутренними перенаправлениями:
index index.html;
try_files $uri $uri.html $uri/ =404;
# like "location ~", but only for matching the original request.
if ($request_uri ~ /index(.html)?$) {
rewrite ^(.*/)index(.html)?$ $1 permanent;
}
if ($request_uri ~ \.html$) {
rewrite ^(.*)\.html$ $1 permanent;
}
(Обратите внимание, что все эти директивы теперь существуют в контексте сервера, без каких-либо блоков местоположения.)