.HTACCESS создает ненужную цепочку перенаправлений 301 — как удалить?

.HTACCESS создает ненужную цепочку перенаправлений 301 — как удалить?

Мой стек:

  • ЛАМПА
  • Апач/2.4.41

Исходная информация:

Недавно я запустил новый веб-сайт для клиента. В процессе редизайна мы решили:

  • Перейти на HTTPS для всего сайта
  • Удалите расширение .php из URL-адресов.
  • Перейти на CMS

Пример СТАРОГО URL:
http://www.example.com/courses/acme-course.php

Пример НОВОГО URL:
https://www.example.com/courses/acme-course

Моя проблема:

При переходе пользователя на один из СТАРЫХ URL-адресов происходит ненужная дополнительная переадресация 301.

Я не понимаю, почему создается дополнительная переадресация 301, а не отправляет пользователя напрямую на правильный целевой URL с помощью одной переадресации 301.

Интересное наблюдение:

Ненужная дополнительная переадресация 301 не происходит, когда я использую СТАРЫЙ URL с HTTPS вместо HTTP.

Пример:
https://www.example.com/courses/acme-course.php _

Использование указанного выше URL-адреса позволит правильно выполнить одинарную переадресацию 301 на правильный целевой URL-адрес:https://www.example.com/courses/acme-course

Вот пример цепочки перенаправлений 301:

Исходный URL-адрес запроса:

http://www.example.com/courses/acme-course.php

1ST 301 Перенаправление (необязательно):

ОТ:

http://www.example.com/courses/acme-course.php

К:

https://www.example.com/index.php?url=courses/acme-course.php

2-е перенаправление 301 (правильный конечный URL-адрес назначения):

ОТ:

https://www.example.com/index.php?url=courses/acme-course.php

К:

https://www.example.com/courses/acme-course

Мой код .htaccess:

# (1) General Settings
<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
</IfModule>

# (2) Force WWW
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{SERVER_ADDR} !=127.0.0.1
    RewriteCond %{SERVER_ADDR} !=::1
    RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# (3) Force HTTPS
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

# (4) URL Routing for CMS
<IfModule mod_rewrite.c>

    RewriteCond %{HTTPS} =on
    RewriteRule ^ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ - [env=proto:http]

    ## Check if file/directory exists
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    ## Route all other URLs to index.php/URL
    RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>

решение1

У вас есть две основные проблемы...

  1. Ваши директивы в неправильном порядке в .htaccessфайле. Ваши HTTP-HTTPS- и wwwканонические перенаправления должны быть удаленыдоваш фронт-контроллер, который направляет URL в вашу CMS. Отсюда и неправильный внешний редирект на /index.php?url=courses/acme-course.php- раскрывающий внутреннюю структуру URL CMS.
  1. Удаление .phpфактически не выполняется вашими .htaccessдирективами?! Я предполагаю, что это должно быть сделано вашей логикой приложения/CMS? Следовательно, это будетвсегдапривести к повторному перенаправлению (поскольку .htaccessперенаправление на HTTPS по тому же URL-пути). Вам нужно сделать что-то вроде следующего в верхней части вашего .htaccessфайла, чтобы удалить .phpрасширение.

    RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
    

ОБНОВЛЯТЬ:Если я изменю порядок правил/условий, останется ли расположение Options +FollowSymlinks прежним?

Это не имеет значения.гдедиректива Optionsпоявляется. Однако логично (с точки зрения читабельности) расположить ее в верхней части. (Директивы Apache не обязательно выполняются в том порядке, в котором они указаны в файле конфигурации, поскольку каждый модуль работает независимо.)

Если предположить, что вы вручную кодируете свой .htaccessфайл, то его можно привести в порядок...

  1. Нет необходимости в (множественных) <IfModule mod_rewrite.c>оболочках. Является ли mod_rewrite необязательным? Будет ли ваш сайт перенесен на несколько серверов, где mod_rewrite не включен?

  2. Нет необходимости в нескольких RewriteEngineдирективах.последнийпример на самом делепобедыи контролирует весь файл.

    Несколько <IfModule>блоков RewriteEngineтипичны для систем, которые автоматически редактируются кодом и/или предназначены для функционирования в нередактированном виде на нескольких серверах.

Итак, ваш .htaccessфайл следует переписать следующим образом в следующем порядке:

Options +FollowSymlinks

# Enable the rewrite engine...   
RewriteEngine On

# ----------------------------------------------------------------------
# | Forcing `https://`                                                       |
# ----------------------------------------------------------------------

# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]


# ----------------------------------------------------------------------
# | Forcing `www`                                                          |
# ----------------------------------------------------------------------

RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# ----------------------------------------------------------------------
# | URL Routing for CMS                                              |
# ----------------------------------------------------------------------

# (3)
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
   
# (4) - Check if physical file exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d  

# (5) - Rewrite all other URLs to index.php/URL
RewriteRule (.*) index.php?url=$1 [L,QSA]

Дополнительные замечания:

  • Переменная окружения PROTOсодержит запрашиваемый протокол. С учетом порядка перенаправлений это всегда будет HTTPS. Причина этой переменной в том, что CMS может перенаправлять на HTTP, если осуществляется доступ к HTTP, или на HTTPS, если осуществляется доступ к HTTPS. Если вы принудительно используете HTTPS, то это на самом деле не применяется. (Хотя эта переменная окружения все еще может использоваться вашим приложением.)

  • Редко следует использовать NCфлаг в отрицательных условиях. Вот почему я удалил его из условия !^www\.. Вы хотите, чтобы он перенаправлял, когда хост не начинается с www.- все строчные буквы. С NCфлагом перенаправление не произойдет WwW.- хотя это в любом случае будет очень редким.

  • Я удалил ненужную проверку HTTPS при каноническом перенаправлении www.

  • Флаг PTв последнем RewriteRuleне требуется в .htaccess. В .htaccessэто поведение по умолчанию (проход).

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

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