
У меня есть сайт Wordpress. Я хочу перенаправить .php URL-адреса на те, у которых нет суффикса .php. .htaccess выглядит следующим образом:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Но когда я посещаюhttps://www.example.com/somepage.php, страница не может быть отображена. В браузере отображается следующая ошибка:
The page isn’t redirecting properly
An error occurred during a connection to www.example.com.
This problem can sometimes be caused by disabling or refusing to accept cookies.
И URL в адресной строке становится https://www.example.com/index.
Если я изменю правило перезаписи следующим образом:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.html$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
И посетитеhttps://www.example.com/somepage.html, он успешно перенаправляется наhttps://www.example.com/somepageи веб-страница отображается нормально. Почему?
решение1
Потому что, поскольку перенаправлениебезусловный, вы снова перенаправляетесьпослеURL был переписан на index.php
(фронт-контроллер WordPress).
Когда вы запрашиваете /somepage.php
:
- Вы перенаправлены на
/somepage
(по первому правилу). Ответ о перенаправлении отправляется обратно клиенту. - При втором запросе
/somepage
внутренне переписывается на/index.php
последнее правило. Затем механизм перезаписи начинает заново (вкаталогконтекст)... /index.php
перенаправляется на/index
(по первому правилу). Ответ на перенаправление отправляется обратно клиенту.- На третьем запросе
/index
внутренне переписывается/index.php
последней перезаписи. Затем механизм перезаписи запускается заново... - Перейти к пункту 3 (застрял в бесконечном цикле перенаправления).
Вкаталогконтекст (например .htaccess
, ) механизм перезаписи не просто делает один проход через скрипт. Он зацикливается до тех пор, пока URL не пройдет без изменений. (Если только вы не используете флаг END
на Apache 2.4 или не происходит внешний редирект 3xx.)
Изменение на remove .html
работает нормально, потому что вы переписываете в /index.php
, который не заканчивается на .html
, поэтому директива redirect (которая удаляет .html
) не совпадает.
Чтобы решить эту проблему, вам нужно избегать перенаправления переписанного запроса. Это можно сделать одним из следующих способов:
использование
END
флага (Apache 2.4+) при последней перезаписи вместоL
предотвращения дальнейших циклов движка перезаписи. Хотя следует избегать изменения стандартных директив WordPress (см. ниже), так что это может быть не предпочтительным вариантом. Это также не работает на Apache 2.2.Или проверьте
.php
расширение поTHE_REQUEST
переменной сервера (которая содержит начальную строку заголовков HTTP-запроса и не изменяется при перезаписи запроса). Например:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC] RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
Или проверьте
REDIRECT_STATUS
переменную окружения, которая пуста при первоначальном запросе и установлена на 200 (как в статусе 200 OK HTTP) при первой успешной перезаписи (это проще, чем довольно сложное регулярное выражение выше). Например:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
Однако вам не следует редактировать код внутри # BEGIN WordPress
раздела, так как WordPress сам пытается это поддерживать и может перезаписать этот код позже. Это правило нужно убратьдомаркер # BEGIN WordPress
комментария. Вам не нужно повторять RewriteEngine On
директиву, которая появляется далее в файле (в разделе WordPress).
Вам нужно будет очистить кэш браузера перед тестированием, так как ошибочный (постоянный) редирект, скорее всего, был кэширован браузером. Сначала протестируйте с 301 (временными) редиректами, чтобы избежать проблем с кэшированием.
Однако это само по себе не позволяет вам получить доступ к .php
файлам без .php
расширения. Поскольку URL без расширения должен быть внутренне переписан обратно в .php
файл.