Загрузка...
Загрузка...
Полный справочник правил редиректов в .htaccess: 301/302, regex-редиректы, смена домена, HTTPS, trailing slash. Готовые примеры для Apache.
Подробное руководство по работе с редиректами: типы, настройка, влияние на SEO. Практические примеры для веб-разработчиков и SEO-специалистов. Лучшие практики и типичные ошибки.
SEOДиагностика и устранение бесконечного цикла редиректов (redirect loop). Причины, типичные сценарии и пошаговые решения для Apache, Nginx и WordPress.
Веб-разработкаПолное руководство по .htaccess для Apache. Редиректы, rewrite правила, безопасность, кэширование, сжатие. Практические примеры для веб-разработчиков и SEO.
SEOПошаговое руководство по поиску и исправлению ошибок 404. Инструменты диагностики, настройка редиректов, кастомные страницы 404. Влияние на SEO и пользователей.
Поделитесь с коллегами или изучите другие материалы блога
Редиректы в .htaccess — один из самых частых сценариев настройки веб-сервера Apache. Смена домена, переход на HTTPS, изменение структуры URL, склейка www — во всех этих случаях нужны корректные правила перенаправления. В этой статье собраны готовые примеры для типичных и нестандартных ситуаций. Перед внедрением правил рекомендуется проверить цепочки редиректов через инструмент проверки редиректов reChecker.
Apache поддерживает несколько способов задания редиректов. Выбор зависит от сложности условия и необходимости использования регулярных выражений.
| Директива | Модуль | Синтаксис | Регулярные выражения |
|---|---|---|---|
Redirect | mod_alias | Простой путь | Нет |
RedirectMatch | mod_alias | Regex | Да |
RewriteRule | mod_rewrite | Regex | Да |
Директива Redirect проще в использовании, но не поддерживает условия. Для сложной логики используется mod_rewrite. Генерировать готовые правила можно в Генераторе .htaccess.
# 301 — постоянный редирект (передаёт ссылочный вес)
Redirect 301 /old-page.html /new-page.html
Redirect 301 /category/old-name /category/new-name
# 302 — временный редирект
Redirect 302 /maintenance /coming-soon
# 307 — временный с сохранением метода (POST остаётся POST)
Redirect 307 /api/submit /api/v2/submit
# 308 — постоянный с сохранением метода
Redirect 308 /old-api /new-api
Важно: при использовании Redirect путь в первом аргументе интерпретируется как префикс. Запрос /old-page.html?id=1 перенаправится на /new-page.html?id=1 — query string сохраняется автоматически.
Когда нужны паттерны, используйте RedirectMatch. Для отладки regex полезен Regex Tester на reChecker.
# Редирект всех .html на версию без расширения
RedirectMatch 301 ^/(.+)\.html$ /$1
# Редирект старых ID страниц
RedirectMatch 301 ^/product/([0-9]+)\.php$ /products/$1
# Редирект датированных URL
RedirectMatch 301 ^/blog/([0-9]{4})/([0-9]{2})/(.+)\.html$ /articles/$3
mod_rewrite даёт максимальную гибкость: условия, захват групп, проверка переменных окружения.
RewriteEngine On
RewriteBase /
RewriteBase задаёт базовый путь для подстановок. На корне сайта обычно /.
| Флаг | Назначение |
|---|---|
R=301 | Код ответа 301 |
R=302 | Код ответа 302 |
L | Last — остановить обработку правил |
NC | No Case — игнорировать регистр |
QSA | Query String Append — добавить исходный query string |
NE | No Escape — не экранировать специальные символы в подстановке |
OR | Или — объединить условия (RewriteCond) |
RewriteEngine On
# Одна страница на другую
RewriteRule ^old-page$ /new-page [R=301,L]
# С сохранением query string
RewriteRule ^search\.php$ /search [R=301,L,QSA]
# Игнорирование регистра
RewriteRule ^About$ /about [R=301,L,NC]
# Захват группы и подстановка
RewriteRule ^blog/post-([0-9]+)\.html$ /articles/$1 [R=301,L]
Обязательный шаг после установки SSL. Весь HTTP-трафик должен перенаправляться на HTTPS.
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Вариант с явным указанием домена:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
Через Redirect (проще, но без условий):
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Две версии сайта создают дублирование контента. Выберите одну каноническую и настройте редирект.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(.+)$ [NC]
RewriteRule ^(.*)$ https://www.%1/$1 [R=301,L]
RewriteEngine On
# Сначала на HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Затем на www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(.+)$ [NC]
RewriteRule ^(.*)$ https://www.%1/$1 [R=301,L]
Подробнее о выборе канонического домена и SEO-аспектах — в руководстве по оптимизации редиректов.
Единообразие URL влияет на индексацию. Выберите один формат.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ /$1/ [R=301,L]
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
Условие !-d предотвращает редирект для реальных директорий (иначе /blog/ перестанет открывать папку).
При переносе сайта на новый домен все старые URL должны вести на соответствующие страницы нового домена.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^old-domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.old-domain\.com$
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]
Сохранение структуры путей:
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L,QSA]
QSA сохраняет параметры: old-domain.com/page?utm_source=google → new-domain.com/page?utm_source=google.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)\.html$ /$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [R=301,L]
# /item.php?id=12345 → /items/12345
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^item\.php$ /items/%1? [R=301,L]
Символ ? в конце подстановки убирает исходный query string. Без него получится /items/12345?id=12345.
# /en/about → /about (удаление префикса языка)
RewriteRule ^en/(.*)$ /$1 [R=301,L]
# Или наоборот: /about → /ru/about
RewriteCond %{HTTP:Accept-Language} ^ru [NC]
RewriteRule ^(.*)$ /ru/$1 [R=302,L]
RewriteCond %{HTTP_USER_AGENT} ^Googlebot [NC]
RewriteRule ^old-sitemap\.xml$ /new-sitemap.xml [R=301,L]
RewriteCond %{REMOTE_ADDR} ^192\.168\.1\.(100|101|102)$
RewriteRule ^(.*)$ /beta/$1 [R=302,L]
RewriteCond %{HTTP_USER_AGENT} (android|blackberry|iphone|ipad|ipod) [NC]
RewriteCond %{HTTP_HOST} !^m\.example\.com$
RewriteRule ^(.*)$ https://m.example.com/$1 [R=302,L]
# /shop/category/old-name/ → /catalog/new-name/
RewriteRule ^shop/category/old-name/(.*)$ /catalog/new-name/$1 [R=301,L]
# Все страницы раздела
RewriteRule ^old-section/(.*)$ /new-section/$1 [R=301,L]
# /page?sort=old → /page?order=new
RewriteCond %{QUERY_STRING} sort=old
RewriteRule ^page$ /page?order=new [R=301,L,QSD]
QSD (Query String Discard) удаляет исходный query string перед добавлением нового.
ErrorDocument 404 /index.html
Или на кастомную страницу:
ErrorDocument 404 https://example.com/404
ErrorDocument 500 https://example.com/500
В одностраничных приложениях все неизвестные пути часто ведут на index.html:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
Здесь [L] без R — внутренняя перезапись, без HTTP-редиректа.
Правила обрабатываются сверху вниз. Рекомендации:
L — останавливайте обработку после срабатывания.RewriteCond %{HTTPS} off перед редиректом на HTTPS).Типичная структура:
RewriteEngine On
RewriteBase /
# 1. Специфичные страницы
RewriteRule ^old-contact$ /contact [R=301,L]
RewriteRule ^legacy-page\.php$ /new-page [R=301,L,QSA]
# 2. HTTP → HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# 3. www / non-www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
После настройки редиректов проверьте:
QSA.Иногда нужно перенаправлять только при определённом статусе. Через ErrorDocument:
ErrorDocument 404 https://example.com/404
ErrorDocument 403 https://example.com/access-denied
ErrorDocument 500 https://example.com/error
Редирект 404 на релевантную страницу (например, поиск по slug):
ErrorDocument 404 /index.php?page=404
По умолчанию RewriteRule не передаёт query string. Добавьте QSA (Query String Append):
RewriteRule ^old-path$ /new-path [R=301,L,QSA]
Запрос /old-path?utm_source=google станет /new-path?utm_source=google.
Удаление query string при редиректе — добавьте ? в конец подстановки:
RewriteRule ^old-path$ /new-path? [R=301,L]
Отдельный поддомен для мобильной версии:
RewriteCond %{HTTP_USER_AGENT} (android|blackberry|iphone|ipad|ipod|mobile) [NC]
RewriteCond %{HTTP_HOST} !^m\.example\.com$
RewriteRule ^(.*)$ https://m.example.com/$1 [R=302,L]
302 — временный, чтобы поисковики не переносили весь вес на m-версию. Для мобильного-first лучше не делать отдельный поддомен.
Требует mod_geoip или mod_geoip2:
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^RU$
RewriteRule ^(.*)$ https://ru.example.com/$1 [R=302,L]
QSA или явно передайте $QUERY_STRING.RewriteRule, неверный путь к файлу, отсутствие RewriteEngine On.Полный обзор возможностей .htaccess — в руководстве по .htaccess.