Рейтинг:2

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

флаг sa

У меня есть сайт Wordpress. Я хочу перенаправить URL-адреса .php на те, у которых нет суффикса .php. .htaccess выглядит следующим образом:

# НАЧАТЬ WordPress
<IfModule mod_rewrite.c>
RewriteEngine включен


Правило перезаписи ^(.*)\.php$ "$1" [R=301,L,NC]


Переписать Базу /
Правило перезаписи ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Правило перезаписи. /index.php [Л]
</ЕслиМодуль>

# ЗАВЕРШИТЬ WordPress

Но когда я посещаю https://www.example.com/somepage.php, страница не может отображаться. В браузере отображается следующая ошибка:

Страница неправильно перенаправляется

    Произошла ошибка при подключении к www.example.com.
    
        Иногда эта проблема может быть вызвана отключением или отказом принимать файлы cookie.

И URL в адресной строке становится https://www.example.com/index.

Если я изменю правило перезаписи как:

# НАЧАТЬ WordPress
<IfModule mod_rewrite.c>
RewriteEngine включен


Правило перезаписи ^(.*)\.html$ "$1" [R=301,L,NC]


Переписать Базу /
Правило перезаписи ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Правило перезаписи. /index.php [Л]
</ЕслиМодуль>

# ЗАВЕРШИТЬ WordPress

И посетить https://www.example.com/somepage.html, он успешно перенаправлен на https://www.example.com/somepage и веб-страница отображается нормально. Почему?

Рейтинг:2
флаг kz

Потому что, поскольку перенаправление безусловный, вы снова перенаправляете после URL был переписан на index.php (фронт-контроллер WordPress).

Когда вы запрашиваете /somepage.php:

  1. Вы перенаправлены на /некоторая страница (по первому правилу). Ответ перенаправления отправляется обратно клиенту.
  2. По второму запросу, /некоторая страница внутренне переписан на /index.php по последнему правилу. Затем механизм перезаписи запускается заново (в каталог контекст)...
  3. /index.php перенаправляется на /показатель (по первому правилу).Ответ перенаправления отправляется обратно клиенту.
  4. По третьему запросу /показатель внутренне переписан на /index.php по последней перезаписи. Затем двигатель перезаписи запускается заново...
  5. Перейти к 3 (застрял в бесконечном цикле перенаправления).

В каталог контекст (как .htaccess) механизм перезаписи не просто выполняет один проход по сценарию. Он повторяется до тех пор, пока URL-адрес не пройдет без изменений. (Если вы не используете КОНЕЦ флаг на Apache 2.4, или происходит внешнее перенаправление 3xx.)

Изменение для удаления .html работает нормально, потому что вы переписываете на /index.php, который не заканчивается .html, поэтому директива перенаправления (которая удаляет .html) не совпадает.

Чтобы решить эту проблему, вам нужно избегать перенаправления переписанного запроса. Вы можете сделать это либо:

  • с использованием КОНЕЦ флаг (Apache 2.4+) при последней перезаписи вместо л чтобы предотвратить дальнейшие циклы механизма перезаписи. Хотя вам следует избегать изменения стандартных директив WordPress (см. ниже), так что это может быть не предпочтительным вариантом. Это также не работает на Apache 2.2.

  • Или проверьте наличие .php продление против ЗАПРОС серверная переменная (которая содержит начальную строку заголовков HTTP-запроса и не изменяется при перезаписи запроса). Например:

    # Удалить расширение ".php" только для "прямых" (не переписанных) запросов
    RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC]
    Правило перезаписи (.+)\.php$ /$1 [R=301,L,NC]
    
  • Или проверьте REDIRECT_STATUS переменная окружения, которая пуста при первоначальном запросе и устанавливается в 200 (как в HTTP-статусе 200 OK) при первой успешной перезаписи (это проще, чем более сложное регулярное выражение выше). Например:

    # Удалить расширение ".php" только для "прямых" (не переписанных) запросов
    Условия перезаписи %{ENV:REDIRECT_STATUS} ^$
    Правило перезаписи (.+)\.php$ /$1 [R=301,L,NC]
    

Однако не следует редактировать код внутри # НАЧАТЬ WordPress раздел, так как сам WordPress пытается поддерживать его и может перезаписать этот код позже. Это правило должно пройти перед в # НАЧАТЬ WordPress маркер комментария. Вам не нужно повторять RewriteEngine включен директива, которая появляется позже в файле (в разделе WordPress).

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

Однако это само по себе не позволяет вам получить доступ .php файлы без .php расширение. Поскольку URL-адрес без расширения необходимо будет внутренне переписать обратно в .php файл.

peter avatar
флаг sa
Во время первого запроса "/somepage.php", после обработки "RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]", механизм перезаписи запускается заново, потому что перезаписанный URL-адрес "/ какая-то страница" не совпадает с исходной?
флаг kz
@peter Во время первого запроса механизм перезаписи немедленно останавливается при перенаправлении, он не запускается заново. Во время _второго запроса_ механизм перезаписи "запускается заново", потому что перезаписанный URL `/index.php` не совпадает с исходным (`/somepage`).Да, механизм перезаписи «запускается заново», потому что URL-адрес изменяется в процессе перезаписи.
peter avatar
флаг sa
так как я могу сказать, запустится ли двигатель перезаписи заново или нет? Оба запроса переписывают URL-адрес на другой, почему второй запрос вызывает перезапуск, а первый запрос - нет?
флаг kz
@peter Если установлен код ответа 3xx (внешнее перенаправление), то в конце текущего прохода через механизм перезаписи механизм перезаписи завершает работу и происходит перенаправление, дополнительных проходов через механизм перезаписи в этом случае нет. В приведенном выше процессе перезаписи всегда завершается перенаправление. Если не было «перенаправления» (например, удаление флага `R` из первого правила), то это приведет к внутреннему циклу перезаписи (ответ клиенту 500 Internal Server Error).
флаг kz
Просто чтобы уточнить, под «перенаправлением происходит» я имею в виду, что ответ перенаправления 3xx отправляется обратно клиенту (в комплекте с заголовком HTTP-ответа «Местоположение» с предполагаемой целью перенаправления).
флаг kz
@peter Я обновил свой ответ, чтобы, надеюсь, прояснить некоторые моменты (относительно перенаправления) и добавил пример, в котором используется `THE_REQUEST` для предотвращения цикла перенаправления. Хотя я по-прежнему считаю, что пример, который я изначально опубликовал (используя env var `REDIRECT_STATUS`), является предпочтительным/самым чистым решением на этом сайте WordPress.
peter avatar
флаг sa
Ваш ответ очень подробный, ясный и полезный. Отличный! Большое спасибо!

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.