Почему не работает перенаправление в .htaccess?

Почему не работает перенаправление в .htaccess?

У меня есть сайт 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:

  1. Вы перенаправлены на /somepage(по первому правилу). Ответ о перенаправлении отправляется обратно клиенту.
  2. При втором запросе /somepageвнутренне переписывается на /index.phpпоследнее правило. Затем механизм перезаписи начинает заново (вкаталогконтекст)...
  3. /index.phpперенаправляется на /index(по первому правилу). Ответ на перенаправление отправляется обратно клиенту.
  4. На третьем запросе /indexвнутренне переписывается /index.phpпоследней перезаписи. Затем механизм перезаписи запускается заново...
  5. Перейти к пункту 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файл.

Связанный контент