Самые популярные способы создания постоянного 301 редиректа (301 Permament Redirect - постоянный редирект), как серверные так и скриптовые. 301-ый код статуса HTTP, возвращается при обращении к определенному ресурсу и означает, что запрашиваемый документ был перенесен на новый адрес, причём на постоянной основе. Получив 301 код статуса HTTP все клиенты (user agents) будут перенаправляться по новому адресу. Обычно при 301 редиректе поисковые роботы производят "склейку" адресов, начального и конечно, как будто это одна страница.
Редирект с 301-ым кодом статуса запроса HTTP это пожалуй наилучший способ сохранить или передать рейтинг сайта. Естественно переадресацию можно выполнять разными способами:
Нижний уровень это переадресация от самого веб сервера. Самый надёжный и быстрый способ.
Далее идёт серверная скриптовая прослойка. Т.е. редирект можно сделать при помощи серверного языка программирования отправив нужные HTTP заголовки.
Ну и самые не надёжные переадресации на верхнем уровне, т.е. в уже в самом HTML и JavaScript коде, который передаётся непосредственно клиенту.
В этом посте я расскажу про все эти способы. Описывать методы 301 редиректа буду в такой же последовательности, что и привёл их выше.
301 редирект в файле .htaccess
На сервере apache, переадресацию можно выполнить с помощью файла дополнительной локальной конфигурации .htaccess (hiper text access). При этом понадобятся включения модулей mod_alias (для поддержки директив Redirect, RedirectPermanent и RedirectMatch) и/или mod_rewrite (для использования директив реврайта).
Редирект с помощью директивы Redirect или RedirectPermanent модуля mod_alias
Redirect 301 /old-page.html http://new-domain.loc/new-page.html или Redirect permanent /old-page.html http://new-domain.loc/new-page.html
Способ явно не подходит для массового редиректа. Все адреса, которые необходимо перенаправить, нужно перечислять один за одним, каждый отдельно на новой строке в новой дерективе Redirect
. Также можно использовать директиву RedirectPermanent, которая предназначена именно для 301 редиректа.
RedirectPermanent /old-url.html http://new-site.loc/new-url.html
В этом случае указывать код статуса не требуется, он уже жёстко вбит для директивы RedirectPermanent
.
Редирект с помощью директивы RedirectMatch
Применение этой директивы позволяет использовать регулярные выражения в задании старых адресов. Т.е. этот редирект идентичен предыдущему, но ещё можно задавать регулярное выражение для старых URL адресов.
Например, при смене серверного языка программирования с PHP на ASP
, можно старые адреса перенаправить следующим образом:
RedirectMatch /(.*)\.php$ /$1.aspx
Все заканчивающееся на .php
перенаправлять на такие же адреса файлов только с расширением .aspx
Редирект с помощью директивы RewriteRule модуля mod_rewrite
Для использования директивы RewriteRule
необходимо удостовериться, что в файле конфигурации сервера Apache httpd.conf
подключен модуль mod_rewrite
, а также влючена опция FollowSymLinks для текущего виртуального хоста. Вообще модуль mod_rewrite
очень мощный и его использование дает много возможностей для перенаправления запросов на любые адреса.
Перенаправление домена с www на не-www
Options +FollowSymLinks RewriteEngine On RewriteCond %{HTTP_HOST} ^www\.(.*) [NC] # Хотя более точно так RewriteCond %{HTTP_HOST} ^www\.(.+) [NC] RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
Это универсальный способ, который действует всегда и код не надо исправлять для каждого конкретного сайта, очень удобно. Директивой +FollowSymLinks
заставляем позволяем серверу отдавать файлы, которые физически находятся за пределами wwwroot директории, но на которые есть ярлыки/ссылки (symbolic link). Далее включаем RewriteEngine
. Описываем условие для следующего правила, в данном случае берём HTTP_HOST
из запроса и смотрим есть ли у него вначале префикс www
, если да то применяется следующего правило описанное в директиве RewriteRule
, а именно, все запросы перенаправяются такой же домен но уже без префикса www
, флаг R
говорит, что нужно использвать 301 редирект, а L
сетует на то, что это последнее правило для выполнения. В формировании нового URL для редиректа в директиве RewriteRule
переменная подстановки %1
берёт доменное имя без www из строки RewriteCond
, т.е. всё, что заключено в круглые скобки, туда имя хоста подставляется из внутренней переменной сервера Apache %{HTTP_HOST}
, которая, в свою очередь берётся из запроса клиента, а переменная строковых GET параметров запроса $1
в диретиве RewriteRule
берётся из той же строки, но первого аргумента, там где описано регулярное выражения параметров запроса, точнее в конечную переменную попадает всё заключённое в круглые скобки регулярного выражения первого аргумента.
Так же есть и альтернативный, более понятный, но не универсальный синтаксис перенаправления домена с www на домен без www.
Options +FollowSymLinks RewriteEngine On RewriteCond %{HTTP_HOST} ^www.domain\.loc$ [NC] RewriteRule ^(.*)$ http://domain.loc/$1 [R=301,L]
или вот так:
Options +FollowSymLinks RewriteEngine On RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] RewriteRule ^(.*)$ http://domain.loc/$1 [R=301,L]
Кстати, я такой дурацкий синтаксис долгое время использовал на своих сайтах, когда не знал, что в директиве RewriteRule
при помощи переменной %1
можно динамически получить имя хоста без www из предыдущей директивы RewriteCond
. Из-за этого приходилось править файл .htaccess для каждого домена, очень муторное дело когда много сайтов, проще использовать вариант который я привёл первым в этом примере, там всё универсально.
Редирект запросов с не-www на домен с www префиксом
Теперь предположим обратную ситуацию, на надо перенправлять на домен с префиксом www. Исходя из выше приведённых примеров и описаний не трудно догадаться как это сделать.
Options +FollowSymLinks RewriteEngine On RewriteCond %{HTTP_HOST} ^domain\.loc$ [NC] RewriteRule ^(.*)$ http://www.domain.loc/$1 [R=301,L]
или же альтернативный, универсальный вариант:
RewriteEngine On RewriteCond %{HTTP_HOST} !^www\.(.*) [NC] RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
Если имя хоста начинается не с www то редиректим на запрошенный хост и добавляем префикс www с точкой вначало.
Редирект с помощью серверного скрипта (отправки HTTP заголовков)
Редирект можно осуществлять также с помощью серверных скриптов, отправляя клиенту необходимые заголовки перенаправления:
HTTP/1.1 301 Moved Permanently Location: http://www.newdomain.loc/newdir/newpage.html
После получения подобных HTTP заголовков любой user agent должен проследовать по адресу указанному в директиве Location
. Стандарт этого заголовка обязывает указывть только полные абсолютные адреса веб ресурсов, включая протокол, никакие относительные адреса не поддерживаются, они будут считатья за ошибку.
Собственно всё, что нам нужно сделать в коде скрпитов, это передать данные HTTP заголовки клиенту.
Отправка HTTP заголовков редиректа на языке PHP
Для отправки заголовков в языке программирования PHP в базовой библиотеке есть специальная функция с одноимённым названием header
. В качестве единственного строчного параметра они принимает заголовок, который впоследствии отдаст клиенту. Каждый заголовок нужно укзать в отдельном вызове функции ибо она топравляет их только по одному. Важно вызывать эту функцию до ночала отправки каких либо данных клиенту т.к. HTTP заголовки всегда отправляются в самом начале ещё до тела страницы.
<?php header(“HTTP/1.1 301 Moved Permanently”); header(“Location: http://www.newdomain.loc/newdir/newpage.html”); exit(); ?>
Вот и весь 301 первый редирект реализованный на PHP!
Отправка HTTP заголовков редиректа на ASP
<%@ Language=VBScript %> <% Response.Status=“301 Moved Permanently” Response.AddHeader “Location”, “http://www.newdomain.loc” response.end %>
Практически всё тоже самое.
Отправка HTTP заголовков редиректа на ASP.NET
Здесь синтаксис очень схож с обычным ASP.
<script runat=“server”> private void Page_Load(object sender, System.EventArgs e) { Response.Status = “301 Moved Permanently”; Response.AddHeader(“Location”,“http://www.new-url.loc”); } </script>
Редиректы на других языках
ColdFusion редирект
<.cfheader statuscode=“301” statustext=“Moved permanently”> <.cfheader name=“Location” value=“http://www.new-url.loc”>
JSP
(Java) редирект
<% response.setStatus(301); response.setHeader( “Location”, “http://www.new-url.loc/” ); response.setHeader( “Connection”, “close” ); %>
CGI
PERL
$q = new CGI; print $q->redirect(“http://www.new-url.loc/”);
Ruby on Rails
def old_action headers[“Status”] = “301 Moved Permanently” redirect_to “http://www.new-url.loc/” end
Осуществление редиректа в web серевере nginx
В веб сервере nginx разумеентся свои правила отличные от apache, однако это не сколько не условжняет работу.
if ($host = ‘old-domain.loc’ ) { rewrite ^(.*)$ http://new-domain.loc$1 permanent; }
Естественно должен быть подключен модуль ngx_http_rewrite_module
.
Осуществление редиректа базовыми средствами HTML
В HTML так же есть базовые методы отправки заголовков. Для этого в блоке head
используются служебные meta
теги. Это не совсем HTTP заголовки ведь передаются они в HTML коде страницы, но суть в том, что любой клиент распознав подобыне инструкции должен их выполнить как если бы это было передано в HTTP заголовках. Конкретно для перенаправления в языке HTML для тега meta
есть атрибут http-equiv
со специальным значением Refresh
(обновить, освежить). Т.е. стандартный редирект на HTML можно сделать так:
<html><head> <meta http-equiv='Refresh' content='0; URL=new-domain.loc'> </head></html>
Атрибут content
указывет на вермя через которое стоит обновить страницу (в секунадах, ноль значит мгновенно) и конечный URL для редиректа.
Я бы не сказал, что это самый лучшый способ редиретка, но всё же он есть и поэтому решил поведать и про него. Вообще данный метод очень старый и вообще не известно, что будет в будущем с этим стандартом, поэтому крайне не рекомендую использовать данный способ для перенаправления.