#apache #.htaccess #mod-rewrite #url-rewriting
#apache #.htaccess #мод-перезапись #переписывание URL-адресов
Вопрос:
У меня, возможно, простая проблема. У меня есть серверные URL-адреса, которые необходимо перенаправить таким образом:
если вызывается URL-адрес «/ abc /», он должен отображать содержимое, расположенное под «xyz.html «
я могу сделать это с
RewriteRule abc$ xyz.html
но «xyz.html » должно быть 301 перенаправление на «/abc», если оно вызывается.
Это моя простая проблема, я ищу решение с нескольких часов.
было бы легко, если бы это было похоже «test.html «и /проверить/. я могу сделать это следующим образом
RewriteRule ^(. ).html$ /$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule !.*.html$ %{REQUEST_URI}.html [END]
Но в моем случае у меня есть куча URL-адресов без шаблона.
Все, что я пробовал, приводит к неправильной конфигурации сервера. Можете ли вы помочь мне с этим примером?
спасибо, kanuddel
Ответ №1:
Не могли бы вы попробовать следующее.
RewriteEngine ON
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/abc/? [NC]
RewriteRule ^(.*) /xyz.html [L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/xyz.html/? [NC]
RewriteRule ^(.*) /abc/? [R=301,L]
Подробное объяснение:
Почему существует цикл перенаправления с обычным написанием правил: Вопрос из OP интересен и противоречив (вроде), почему, потому что, допустим, мы пишем 1-е правило для перенаправления (в серверной части) с abc
URL-адреса на xyz.html
него, будет работать нормально. Но затем, когда мы пишем наше 2-е правило, которое заключается в том, чтобы переписать URL-адрес с xyz.html
на abc/
, который в точности противоположен первому правилу. Следовательно, это становится циклом, как можно скорее выполняются 1-е правила, оно переходит ко 2-му правилу и возвращает его к 1-му правилу, таким образом, БЕСКОНЕЧНЫЙ ЦИКЛ ПЕРЕНАПРАВЛЕНИЯ (до 50 циклов или около того).
Как предотвратить цикл перенаправления?
-
Во-первых, поскольку оба правила прямо противоположны друг другу, поэтому при обычном написании правил это станет циклом, теперь как мы можем предотвратить превращение его в цикл? Ответ использует:
RewriteCond
(объяснено на следующем шаге) -
Я использовал ПЕРЕМЕННУЮ СРЕДЫ с именем
ENV:REDIRECT_STATUS
, значение которой будет иметь любой статус перенаправления. 2 вещи, которые нам нужно понять об этой переменной.1 — Без перенаправления запроса его значение по умолчанию равно NULL.
2 — Всякий раз, когда мы выполняем успешное перенаправление, его значение становится 200 (НЕНУЛЕВЫМ), что мы можем использовать в нашей части условий.
Подробное объяснение правил htaccess:
-
Теперь перейдем к части с объяснением условия: в RewriteRule
RewriteRule ^(.*) /xyz.html [L]
я НЕ переписывал URL-адрес в браузере, почему из-за ПРАВИЛА БОЛЬШОГО ПАЛЬЦА мы всегда хотим показывать пользователям УДОБНЫЕ URL-адреса, поэтому переменная средыENV:REDIRECT_STATUS
здесь всегда будет равна НУЛЮ. -
Теперь перейдем ко 2-му RewriteRule,
RewriteRule ^(.*) /abc/? [R=301,L]
где пользователь уже использует неудобный для пользователя URL-адрес, поэтому первым делом мне нужно переписать URL-адрес в браузере на удобный для пользователя URL-адрес, следовательноR=301
(здесь используется перенаправление с постоянным флагом). Как только перенаправление произойдет с помощью этого условия, 1-е условие начнет завершаться сбоем, почему, потому что это проверяет, имеет лиREDIRECT_STATUS
переменная значение NULL, чего НЕТ после выполнения перенаправления из 2-го условия. Следовательно, это предотвращает цикл с помощью этого небольшого трюка 🙂
Ответ №2:
Спасибо за отличное объяснение!
Я попробовал это со вторым URL-адресом, где «/ xxx /» должен отображаться «zzz.html » Но это дало мне Неверное представление. Я попытался сократить его следующим образом:
RewriteEngine ON
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/abc/? [NC]
RewriteRule ^(.*) /xyz.html [L]
RewriteCond %{REQUEST_URI} ^/xxx/? [NC]
RewriteRule ^(.*) /zzz.html [L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/xyz.html/? [NC]
RewriteRule ^(.*) /abc/? [R=301,L]
RewriteCond %{REQUEST_URI} ^/zzz.html/? [NC]
RewriteRule ^(.*) /xxx/? [R=301,L]