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

Мой стек:

  • LAMP
  • Apache / 2.4.41

Общая информация:

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

  • Переключиться на HTTPS по всему сайту
  • Удалить расширение .php из URL-адресов
  • Переключиться на CMS

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

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

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

Ненужный дополнительное перенаправление 301 происходит, когда пользователь переходит на один из СТАРЫХ URL-адресов.

Я не понимаю, почему создается дополнительное перенаправление 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

TO:[12156 impressionhttps://www.example.com/index.php?url=courses/acme-course.php

2ND 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
задан 12 January 2020 в 00:16
1 ответ

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

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

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

UPDATE: Если я переупорядочу правила/условия, останется ли неизменным мое размещение Options +FollowSymlinks?

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

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

  1. Нет необходимости в (множественных) обёртках. Опционально ли mod_rewrite? Портируется ли ваш сайт на несколько серверов, где mod_rewrite не включен?

  2. Нет необходимости в множественных директивах RewriteEngine. Последний последний экземпляр на самом деле выигрывает и управляет всем файлом.

    Несколько блоков и 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, то на самом деле это не применимо. (Хотя этот вариатор env все еще может быть использован вашим приложением.)

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

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

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

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

0
ответ дан 13 January 2020 в 07:04

Теги

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