Удаление 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;
}
(Обратите внимание, что все эти директивы теперь существуют в контексте сервера, без каких-либо блоков местоположения.)