.htaccess mod_rewrite слишком много перенаправлений

Чтобы прояснить ситуацию,это НЕ повторяющийся вопрос, как этот , поскольку суть вопроса отличается. Я пытаюсь перенаправить пользователей, которые пытаются получить доступ к сайту с помощью языкового кода (обычно en или cz ), на index.php с языком набор переменных. Сам сайт может распознавать только настройки английского и чешского языков, все остальные перенаправляются на основе геолокации IP посетителя (с использованием внешнего онлайн-API JSON). Но проблема в том, что этот браузер продолжает перенаправлять и выдает ошибку, что произошло слишком много перенаправлений. Что случилось? Пытался найти ошибку, но ничего не обнаружил.

Это полный .htaccess файл:

Options -Indexes

RewriteEngine on
RewriteRule ^[a-z]{2,3}/$ /index.php?lang=$1
RewriteRule ^blog/?(.*)$ //blog.czghost.czlh/$1 [R=301]
RewriteRule ^ftp/?(.*)$ //ftp.czghost.czlh/$1 [R=301]

Кроме того, если пользователь пишет в index.php? Lang = $ 1 , мне нужно вместо этого перенаправить его на хороший вариант URL. Я искал в Интернете, но мне это кажется слишком сложным: (

Я тестирую сайты на своем сервере WAMP на моем компьютере с Windows, прежде чем он будет готов к развертыванию в Интернете.

2
задан 5 April 2018 в 20:22
1 ответ

Вы на самом деле не указали запрашиваемые URL-адреса, запускающие цикл перенаправления?

Однако из опубликованных вами директив может показаться, что любой запрос формы / blog или / ftp приведет к циклу перенаправления.

 RewriteRule ^ blog /?(.*)$ //  blog.czghost.czlh / 1 доллар США [R = 301]
RewriteRule ^ ftp /?(.*)$ //ftp.czghost.czlh/$1 [R = 301]
 

Apache mod_rewrite не поддерживает зависящие от протокола URL-адреса в подстановке RewriteRule - они просто рассматриваются как относительные к корню (т. Е. URL-путь относительно корня документа). Вы, вероятно, видите результат этого цикла перенаправления в адресной строке своего браузера?Это будет примерно так:

  • Первоначальный запрос: http://example.com/blog/xyz
  • Перенаправляет на http://example.com//blog.czghost.czlh/ xyz
  • Перенаправляет на http://example.com//blog.czghost.czlh/.czghost.czlh/xyz
  • Перенаправляет на http://example.com//blog.czghost .czlh / .czghost.czlh / .czghost.czlh / xyz
  • и т. д.

Вам необходимо включить протокол. Например:

RewriteRule ^blog/?(.*)$ https://blog.czghost.czlh/$1 [R=301,L]

Я также включил флаг L ( last ), так как вы хотите, чтобы перенаправление запускалось немедленно, не подвергаясь риску дальнейшей перезаписи. Это действительно должно произойти до внутренней перезаписи (которая переписывает в index.php ).

Вам нужно будет убедиться, что вы очистили кеш браузера, так как ошибочный 301 ( постоянный ]) перенаправление будет кешировано браузером. По этой причине может быть проще протестировать с 302 (временными) перенаправлениями.

Правила вашего блога и ftp могут обрабатываться одной директивой, используя чередование . Например:

RewriteRule ^(blog|ftp)/?(.*)$ https://$1.czghost.czlh/$2 [R=301,L]

 RewriteRule ^ [a-z] {2,3} / $ /index.php?lang=$1
 

В шаблоне RewriteRule нет группы захвата (т. Е. Заключенного в скобки подшаблона), поэтому обратная ссылка $ 1 всегда будет пустой. Это должно быть переписано как:

RewriteRule ^([a-z]{2,3})/$ /index.php?lang=$1 [L]

Опять же, я включил флаг L , чтобы предотвратить дальнейшую перезапись. Обратите внимание, что ожидается, что в конце пути URL будет суффикс косой черты. Таким образом, только URL-адреса вида / blog / en / (с суффиксом косой черты) будут успешно переписаны (хотя, возможно, это не имеет отношения к этому).

Итак, в целом, это следует переписать примерно так :

RewriteRule ^(blog|ftp)/?(.*)$ https://$1.czghost.czlh/$2 [R=301,L]
RewriteRule ^([a-z]{2,3})/$ /index.php?lang=$1 [L]

Кроме того, если пользователь пишет в index.php? Lang = $ 1 , мне нужно вместо этого перенаправить его на удобный вариант URL.

Вы можете сделать это с помощью дополнительного перенаправления до вышеуказанных директив. Например:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^lang=([a-z]{2,3})$
RewriteRule ^(index\.php)?$ /%1/? [R=301,L]

Вам необходимо использовать директиву RewriteCond , чтобы проверить строку запроса на соответствие серверной переменной QUERY_STRING (это невозможно сделать в RewriteRule ] директива). Предыдущая проверка переменной среды REDIRECT_STATUS должна гарантировать, что мы обрабатываем только начальные запросы, а не перезаписываем запросы более поздней директивой, которая переписывает URL-адрес на /index.php?lang=xyz . Переменная окружения REDIRECT_STATUS пуста при начальном запросе, но получает значение «200» (как в 200 OK - статус HTTP) после первой успешной перезаписи .

Это будет соответствует либо index.php , либо пустому пути URL (например, /? lang = xyz ). % 1 - это обратная ссылка на последний совпавший CondPattern (в отличие от $ N , который является обратной ссылкой на шаблон RewriteRule ]). ? в конце подстановки RewriteRule необходим для удаления строки запроса из перенаправленного URL-адреса (в качестве альтернативы можно использовать QSD flag на Apache 2.4 +).

Опять же, лучше сначала протестировать с 302 (временным) перенаправлением, которое не будет кэшироваться браузером.

(Из комментариев:) Единственное, что работает правильно , это перенаправление / ftp / . / blog / перенаправление остается с неизмененным URL-адресом на пустой странице

Вы должны убедиться, что в файловой системе нет физического каталога с тем же именем, т.е. / блог . И что в этом подкаталоге нет дополнительного файла .htaccess , который мог бы его переопределить. Также убедитесь, что нет файла с тем же базовым именем blog . например. blog.html или blog.php и т. Д. Если есть, то вам нужно убедиться, что MultiViews (часть mod_negotiation) не включен. т.е. Параметры -Индексы -MultiViews . Если MultiViews включен, Apache выполнит внутренний подзапрос для /blog.php (например), прежде чем mod_rewrite сможет перезаписать URL.

Резюме

Options -Indexes -MultiViews

RewriteEngine on

# Redirect direct requests for "index.php?lang=xyz" to "/xyz/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^lang=([a-z]{2,3})$
RewriteRule ^(index\.php)?$ /%1/? [R=301,L]

# Redirect "blog" or "ftp/<anything>" to subdomain
RewriteRule ^(blog|ftp)/?(.*)$ https://$1.czghost.czlh/$2 [R=301,L]

# Internally rewrite "/xyz/" to "/index.php?lang=xyz"
RewriteRule ^([a-z]{2,3})/$ /index.php?lang=$1 [L]
3
ответ дан 3 December 2019 в 10:33

Теги

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