Главная страница » Блог » SEO-заметки

Редирект htaccess для WordPress с удалением множества слешей /// на конце и многое другое

Введение

В данной статье не буду сильно углубляться в теорию работы Apache и синтаксиса написания правил mod_rewrite для .htaccess, а так же регулярных выражений, но стоит подметить важные моменты в логике конфигурационного файла и самого веб-сервера.

Далее для общего понимания директивы RewriteRule будем именовать правилами, а директивы RewriteCond — условиями.

Итак те самые важные моменты, которые помогут быстрее разобраться в «магии» редиректов:

  1. Директива RewriteRule может использоваться как для создания нового рабочего URL-адреса на сайте, так и просто 301 редиректа. Рассмотрим два этих применения соответственно:

    1) Директива «RewriteRule Шаблон Цель [флаги]» говорит серверу открывать Цель (это должен быть реальный файл на сервере, например index.php) по заданному Шаблону (то что ведет в URL-адрес пользователь)

    Например, правило «RewriteRule /shop/ index.php?page=shop» будет указывать серверу, что при открытии пользователем адреса «https://domain.com/shop/» нужно выполнить PHP-скрипт index.php, в котором будет обрабатываться GET-параметр «page» с значением «shop» ($_GET[«page»] = «shop»).

    2) Если в конце RewriteRule используется флаг [R=301], то открытие реального файла по новому URL-адресу не случиться, а просто выполниться перенаправление, на указанный в Цели адрес.

    Например, правило «RewriteRule /shop/ https://%{HTTP_HOST}/shop-2/ [R=301,L]» просто перенаправит посетителя сайта с «https://domain.com/shop/» на «https://domain.com/shop-2/».
  2. Используемые в условиях RewriteCond переменные Apache-сервера (например %{HTTP_HOST}) можно изучить вот здесь и тут.
  3. Разница между %1 и $1 в том, что аргумент с процентом («%1») выводит попадание в группу взятую в скобки «()» в предыдущих условиях RewriteCond, а аргумент с долларом («$1») выводит попадание в группу «()» в Шаблоне от RewriteRule.

    Например разберем следующие директивы:

    RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
    RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

    Здесь %1 это наш домен без www (взят из условия RewriteCond), а $1 это адрес (взят из самого правила RewriteRule). Флаг [NC] просто означает, что условие регистронезависимое.
  4. Браузеры кешируют редиректы! При этом перезагрузку нужно делать через «инструменты разработчика» или просто открывать страницу в НОВОМ окне в режиме инкогнито. Причем старые страницы в режиме инкогнито надо закрывать.

Отладка и проверка написанных правил

Для максимально комфортной работы пригодится онлайн-инструменты для написания регулярных PERL-выражений и проверки срабатывания самих правил в файле htaccess.

Я для себя нашел сайт regex101.com, который является супер-удобным инструментом для изучения и написания регулярных выражений.

А для онлайн тестирования настроенных правил в htaccess нет, на мой скромный взгляд, лучше сайта, чем htaccess.madewithlove.com.

Стоит подметить, что для анализа цепочки 301-х редиректов нужно каждый раз забирать результат, из поля «Output url» и прогонять уже с новой ссылкой ваш тест.

Например вот так нужно анализировать цепочку перенаправлений c HTTP на HTTPS, а так же с подкатегорий 4-го уровня на 3-хуровневую структуру (/category-endpoint/parrent-categoty/child-categoty/ —> /category-endpoint/child-categoty/).

1. Забираем результат с «Output url» после преобразования в первый раз:

Редирект htaccess для Wordpress с удалением множества слешей /// на конце и многое другое

2. Вставляем результат для нового теста и получаем конечный вариант в «Output url»:

Редирект htaccess для Wordpress с удалением множества слешей /// на конце и многое другое

Практические примеры

Удаление лишних слешей на конце адреса («//»)

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^\/{1}([^\/].*[^\/])(\/{2,})$ [OR,NC]
RewriteCond %{REQUEST_URI} ^(.*[^\/])$ [NC]
RewriteRule (.*) https://%{HTTP_HOST}/%1/ [R=301,L]

Перенаправление с HTTP на HTTPS

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Header always set Content-Security-Policy "upgrade-insecure-requests;"

Перенаправление с www на без www

RewriteCond %{HTTP_HOST} ^www\.(.*)$
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

Двухуровневые категории каталога товаров

Бывает встречается чисто SEO-задача — сделать плоскую структуру категорий интернет-магазина, чтоб все товары имели шаблонный путь типа «/products/product-name/», а категории «/product-category/category-name/».

Для страниц продуктов все делается через настройки постоянных ссылок:

Редирект htaccess для Wordpress с удалением множества слешей /// на конце и многое другое

А вот для категорий нужно делать правило в htaccess:

RewriteCond %{REQUEST_URI} ^\/product-category\/([^\/]*)\/([^\/]*)\/(?=[^\/]*$)
RewriteRule . /product-category/%2/ [R=301,L]

Конечный листинг файла .htaccess для WordPress

Если что порядок директив выбран не случайно, и если его поменять местами, то возможно зацикливание редиректов!

<IfModule mod_rewrite.c>
  RewriteEngine On

  # Редирект: /product-category/verhnjaja-odezhda/bombery/ --> /product-category/bombery/
  RewriteCond %{REQUEST_URI} ^\/product-category\/([^\/]*)\/([^\/]*)\/(?=[^\/]*$)
  RewriteRule . /product-category/%2/ [R=301,L]
 
  # Редирект: HTTP --> HTTPS
  RewriteCond %{HTTP:X-Forwarded-Proto} !https
  RewriteCond %{HTTPS} off
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
  Header always set Content-Security-Policy "upgrade-insecure-requests;"
  
  # Обязательные директивы для WP!!!
  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.php [L]

  # Редирект: /category/// --> /category/ OR /category --> /category/
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_URI} ^.*\.[^html]$ [NC]
  RewriteCond %{REQUEST_URI} ^\/{1}([^\/].*[^\/])(\/{2,})$ [OR,NC]
  RewriteCond %{REQUEST_URI} ^(.*[^\/])$ [NC]
  RewriteRule (.*) https://%{HTTP_HOST}/%1/ [R=301,L]

  # Редирект: www -> без www
  RewriteCond %{HTTP_HOST} ^www\.(.*)$
  RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

  # Обычные 301-е редиректы 
  Redirect 301 /product-category/coats/ /product-category/verhnjaja-odezhda/ljogkie-kurtki-i-vetrovki/
  Redirect 301 /product-category/kostjum-muzhskoj/ /shop/
  Redirect 301 /product-category/bomber-muzhskoj/ /product-category/verhnjaja-odezhda/bombery/
  Redirect 301 /product-category/dzhinsy-muzhskie/ /product-category/dzhinsy/
  Redirect 301 /product-category/dzhinsy-muzhskie-2022/ /product-category/dzhinsy/
  Redirect 301 /product-category/dzhinsy-muzhskie-2023/ /product-category/dzhinsy/
  Redirect 301 /product-category/shirts/ /product-category/futbolka/
  Redirect 301 /product-category/zhiletka-muzhskaja/ /product-category/zhilety/
  Redirect 301 /product-category/obuv-novoe-postuplenie-2022/ /product-category/obuv-muzhskaja/

</IfModule>