Одна из наиболее частых причин использования файла
.htaccess, является потребность в перенаправлении посетителей сайта с одного адреса на другой, обычно это называют
301 редирект. Например был изменен адрес страницы или название каталога, изменилось имя домена и т.д. Эти вопросы легко решаются с помощью .htaccess. Но при этом стоит понимать, что иногда правила переадресации и формирования URL адресов формирует сама CMS (система управления сайтом) и в таком случае не всегда есть возможность решить определенные задачи при помощи .htaccess.
Для редиректа можно использовать директивы Redirect, RedirectMatch и возможности модуля
mod_rewrite.
Redirect — это самая простая директива для создания редиректа, если вам просто нужно перенаправить посетителей с одного адреса на другой, этот метод вполне подходит.
RedirectMatch — является более продвинутой директивой для перенаправлений, чем Redirect. В ней можно использовать
регулярные выражения и
обратные связи.
mod_rewrite — самое мощное средство не только для редиректа, но и для других видов преобразования. Для построения правил с помощью
mod_rewrite используются директивы
RewriteCond и
RewriteRule.
Рассмотрим типичные виды перенаправлений и их решение при помощи указанных выше директив
C одной страницы сайта на другую
Часто бывает так, что был изменен адрес целевой страницы и очень не хочется, что бы посетителям при обращении к старому адресу отдавалась 404 ошибка.
Redirect 301 /old-url /new-url
RedirectMatch 301 test$ http://some-site/test2
RewriteRule ^old-url$ /new-url [R=301]
C одной страницы сайта на другой сайт
При запросе определенной страницы, пользователя перенаправляет на другой сайт.
Redirect 301 /old-url http://newsite.com/
RedirectMatch 301 test$ http://newsite.com/
RewriteRule ^old-url$ http://newsite.com/ [R=301]
Со всех страниц одного сайта на главную страницу другого сайта
То есть, не зависимо от запрошенного адреса, перенаправление будет производится на главную страницу.
Redirect 301 / http://newsite.com/
RedirectMatch 301 /$ http://newsite.com/
RewriteRule ^(.*)$ http://newsite.com/ [R=301]
Такой вид редиректа не совсем подходит, если мы сменили домен для сайта и хотим перенаправлять посетителей на новый адрес сайта. Нам желательно перенаправлять пользователя на запрошенную им страницу, но на новом домене (http://oldsite.com/test -> http://newsite.com/test).
Со всех адресов одного сайта, на такие же адреса другого сайта
RedirectMatch 301 /(.*)$ http://newsite.com/$1
RewriteRule ^(.*)$ http://newsite.com/$1 [R=301]
Редирект с www на без www (www.some-site.com -> some-site.com)
Частая проблема, сайт доступен по обоим адресам, и с www и без www.
RewriteCond %{HTTP_HOST} ^www.(.*)$
RewriteRule ^(.*)$ http://%1/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.some-site.com.ru$ [NC]
RewriteRule ^(.*)$ http://some-site.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]
RewriteRule ^(.*) http://%1/$1 [L,R=301]
В целом эти три примера практически идентичны, различаются только формой записи
Редирект с без www на www (some-site.com -> www.some-site.com)
RewriteCond %{HTTP_HOST} ^([^www].*)$
RewriteRule ^(.*)$ http://www.%1/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^some-site.com$ [NC]
RewriteRule ^(.*)$ http://www.some-site.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^www.some-site.com$ [NC]
RewriteRule ^(.*)$ http://www.some-site.com/$1 [R=301,L]
Редирект с адресов без слеша на адреса на со слешем
Здесь довольно много вариантов решения и очень много зависит непосредственно от сайт и от того, как формируются адреса, все возможные варианты перечислять не будем.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ /$1/ [R=301,L]
Это самый простой пример, сюда можно еще добавить проверку URL адреса на содержание GET параметров, что бы c адреса вида /test?id=1&page=5 не было перенапрвления на /test/?id=1&page=5. И проверку на содержание расширения файла, что бы адреса вида /test.html не превращались в /test.html/.
RewriteCond %{QUERY_STRING} !.+
RewriteCond %{REQUEST_URI} !.
%{QUERY_STRING} — эта
переменная сервера содержит GET параметры, ".+" — означает, что должен быть как минимум один символ, восклицательный знак указывает на несоответствие шаблону. То есть, если переменная %{QUERY_STRING} не содержит ни одного символа, выполняем правило.
%{REQUEST_URI} — эта переменная содержит запрошенный адрес, "!."
— не должен содержать точку. То есть, если в запросе нет точки, правило выполняем. Можно дополнительно уточнить расширения, если в этом есть необходимость:
RewriteCond %{REQUEST_URI} !.(html|htm|php|txt)
В итоге получаем такое правило:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !.
RewriteCond %{QUERY_STRING} !.+
RewriteRule ^(.*)$ /$1/ [R=301,L]
Редирект с адресов со слешем на адреса на без слеша
В целом тут картина примерно та же, что и в предыдущем примере, правило будет выглядеть так:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{QUERY_STRING} !.+
RewriteRule ^(.*)/$ /$1 [R=301,L]
Редирект с дублей главной страницы /index.php или /index.html на главное зеркало сайта
Часто CMS создают дули главной страницы сайта, доступные по адресам /index.php или /index.html. Это безусловно плохо влияет на seo оптимизацию сайта. Решается это довольно просто:
RewriteCond %{REQUEST_URI} /index.(php|html|htm)
RewriteRule ^(.*)$ / [R=301,L]
Теперь при запросе http://somesite.com/index.php, http://somesite.com/index.html или http://somesite.com/index.htm будет производится редирект на главную страницу http://somesite.com/. Но здесь не учтен один момент. Некоторые CMS формируют URL адреса с GET параметрами после /index.php (/index.php?option=sometext&view=sometext&Itemid=2
) и если оставить текущее правило, с адреса с GET параметрами будет также производится редирект на главную страницу. Добавляем проверку на GET параметры:
RewriteCond %{REQUEST_URI} /index.(php|html|htm)
RewriteCond %{QUERY_STRING} !.+
RewriteRule ^(.*)$ / [R=301,L]
Теперь редирект с адресов вида
/index.php?option=sometext&view=sometext&Itemid=2 производится не будет. Но здесь опять не учтен один момент, будут также доступны адреса вида /index.html?option=sometext&view=sometext&Itemid=2 и
/index.htm?option=sometext&view=sometext&Itemid=2. Конечно не супер страшно, но все же лучше от этого избавится, тем более такая возможность есть. Вариант только один, вместо одного правила, написать два:
RewriteCond %{REQUEST_URI} /index.php
RewriteCond %{QUERY_STRING} !.+
RewriteRule ^(.*)$ / [R=301,L]
RewriteCond %{REQUEST_URI} /index.(html|htm)
RewriteRule ^(.*)$ / [R=301,L]
Редирект с HTTP на HTTPS
Это необходимо делать, при установке
SSL сертификата для сайта, что бы все пользователи использовали только защищенное соединения по протоколу
HTTPS.
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Но у меня такой вариант вызывал зацикливание — бесконечный редирект. Опытным путем было выяснено, что не работает условие RewriteCond, по сути оно просто не учитывалось. Это условие должно проверять наличие соединения по HTTPS и если его нет — выполнять директиву RewriteRule, делать редирект на HTTPS. Поэтому я нашел другое решение.
RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Это решение отлично сработало. Вообще вариантов довольно много, ниже еще несколько.
RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTP:SSL} !1
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=301]