301 редирект для дублей главной страницы

Проблема, которую решают эти правила встречается очень часто.
Многие CMS грешат тем, что главная страница открывается у них по 2-м, 3-м и более адресам.
Например для ModX это:

  • /index (или home — alias главной страницы)
  • /index.php (адрес входного скрипта)
  • //// (2 и более слешей)

Все это пагубно сказывается на SEO-параметрах главной страницы. В этом рецепте я расскажу как решить этот вопрос.

Редирект на главную с /index.php или /index.html

apache# example.com/index.php OR example.com/index.html -> example.com

RewriteCond %{THE_REQUEST} ^GET\s/index\.(php|html)\sHTTP/[0-9.]+
RewriteRule ^.*$ http://%{HTTP_HOST}/ [R=301,L] 

Для HTTPS следует во второй строке заменить протокол на https://

В первой строке правила мы проверяем чтобы запрашивалась только index.php без GET-параметров (те, которые идут после знака вопроса в URL).
Это нужно делать потому, что при обработке ЧПУ, многие движки перенаправляют все запросы на свой входной скрипт в виде подобной строки:
/index.php?q=somepage
Если этого не учесть, мы можем получить бесконечный редирект на главную с любой страницы.
Мы, также, делаем редирект только при запросе методом GET, чтобы не получить обнуления POST-данных, к примеру, при отправке их на /index.php вместо /.

Первую строку правила можно корректировать под конкретный случай.
Например, чтобы решить 1-й и 2-й варианты для ModX, правило можно переписать следующим образом:

apache# example.com/home OR example.com/index.php OR example.com/index.html -> example.com

RewriteCond %{THE_REQUEST} ^GET\s/(home|index\.(php|html))\sHTTP/[0-9.]+
RewriteRule ^.*$ http://%{HTTP_HOST}/ [R=301,L] 

С помощью нового регулярного выражения мы говорим правилу срабатывать на /home, на /index.php и на /index.html

Редирект на главную со слешевых дублей (///)

apache# example.com////// -> example.com

RewriteCond %{HTTP_HOST} !=""
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
RewriteCond %{THE_REQUEST} ^[A-Z]+\s(.*/)/+\sHTTP/[0-9.]+$
RewriteRule .* http://%{HTTP_HOST}/%1 [R=301,L] 

Тут сложность в том, что сервер сам преобразует все повторяющиеся слеши в один еще до прохода по правилам в .htaccess. По этой причине мы работаем с полной строкой HTTP-запроса, которую браузер передал серверу.
В первой строке мы проверяем чтобы переменная %{HTTP_HOST} не была пуста, т.е. содержала домен.
Во 2-й и 3-й строках мы проверяем наличие идущих подряд слешей в начале или конце пути.
Если эти условия подходят мы делаем редирект, собирая правильный URL без лишних слешей.
 

17 февраля 2016