RewriteRule — это директива модуля Apache Mod Rewrite, которая позволяет на лету переписывать URL-адреса согласно заданным правилам, а сам mod_rewrite работает через файл .htaccess и даёт вебмастеру полный контроль над тем, как сервер обрабатывает запросы посетителей.
За 20 лет в продвижении сайтов я вывел сотни ресурсов в топ Яндекса и Google, и могу сказать с уверенностью: без понимания синтаксиса RewriteRule и примеров RewriteRule серьёзная работа с ЧПУ, редиректами и защитой просто невозможна.
Разберёмся в теме подробно, без воды, с реальными рабочими инструкциями.
Содержимое:
Apache Mod Rewrite — это один из самых мощных модулей веб-сервера Apache. Он включён по умолчанию почти на всех хостингах, но по умолчанию ничего не делает. Чтобы он заработал, нужно написать правила в файле .htaccess (или в конфигурации виртуального хоста).
Зачем вообще нужен mod_rewrite:
index.php?id=15&cat=3www и без www, с http и httpsВажный нюанс: если ваш сайт работает на Nginx, а не на Apache, то mod_rewrite там не используется — вместо него применяются директивы rewrite и location в конфиге Nginx. Синтаксис другой, логика похожая. Узнайте: DeepSeek R2: что это за модель ИИ, как она работает и что дает.
Базовая конструкция правила выглядит так:
RewriteRule шаблон подстановка [флаги]
Разберём каждую часть.
Это регулярное выражение, которое применяется к части URL после доменного имени. Сервер сравнивает запрошенный путь с шаблоном и, если есть совпадение, выполняет подстановку.
Примеры шаблонов:
^old-page\.html$ — точное совпадение со строкой old-page.html^products/([0-9]+)$ — захватывает число после products/^blog/(.*)$ — захватывает всё, что идёт после blog/Специальные символы в регулярках:
| Символ | Значение |
|---|---|
^ |
Начало строки |
$ |
Конец строки |
. |
Любой символ |
\. |
Точка как literal |
() |
Группировка и захват |
[] |
Набор символов |
+ |
Одно и более повторений |
* |
Ноль и более повторений |
? |
Ноль или одно повторение |
То, во что превратится URL после обработки. Здесь можно использовать захваченные группы из шаблона через $1, $2 и так далее.
Пример:
RewriteRule ^products/([0-9]+)$ /product.php?id=$1 [L]
Запрос site.com/products/42 превратится в site.com/product.php?id=42, но в адресной строке пользователь увидит красивый URL.
Флаги пишутся в квадратных скобках через запятую и меняют поведение правила. Самые важные:
[L] (Last) — последнее правило, дальше обработка не идёт. Почти всегда нужен.[R=301] — постоянный редирект. Для SEO это основной флаг.[R=302] — временный редирект. Используйте осторожно.[NC] (No Case) — игнорировать регистр.[QSA] (Query String Append) — добавить существующие GET-параметры к новому URL.[NE] (No Escape) — не экранировать спецсимволы.[F] (Forbidden) — вернуть код 403.[G] (Gone) — вернуть код 410 (страница удалена навсегда).[PT] (Pass Through) — передать обработанный URL дальше.Часто одного шаблона мало — нужно учитывать дополнительные условия: существует ли файл, какой домен запрошен, с какого сайта пришёл пользователь. Для этого используется RewriteCond.
Синтаксис:
RewriteCond строка_для_проверки условие
RewriteRule ...
Условие применяется к правилу, которое идёт сразу после него. Можно писать несколько условий подряд — они связываются логическим «И» (по умолчанию) или «ИЛИ» (с флагом [OR]).
Примеры условий:
%{REQUEST_FILENAME} !-f — файл не существует%{REQUEST_FILENAME} !-d — директория не существует%{HTTP_HOST} ^www\.(.*)$ [NC] — запрошен домен с www%{HTTPS} !on — соединение не защищённое%{HTTP_REFERER} !^https://(www\.)?mysite\.com — запрос не с нашего сайтаПеременные, которые часто используются:
%{REQUEST_URI} — запрошенный путь%{QUERY_STRING} — GET-параметры%{HTTP_HOST} — домен%{HTTP_USER_AGENT} — браузер пользователя%{REMOTE_ADDR} — IP-адрес посетителя%{HTTPS} — статус SSLПерейдём к конкретике. Ниже — рабочие примеры, которые я использую на проектах.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Обратный вариант (добавить www):
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
Совет: выберите один вариант и придерживайтесь его везде. Смешанные редиректы создают петли.
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Если хостинг работает через прокси (Cloudflare, например), используйте:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
RewriteRule ^catalog/([a-z0-9-]+)/?$ /catalog.php?category=$1 [L,QSA]
RewriteRule ^catalog/([a-z0-9-]+)/page-([0-9]+)/?$ /catalog.php?category=$1&page=$2 [L,QSA]
Теперь site.com/catalog/shoes/ и site.com/catalog/shoes/page-2/ работают красиво.
RewriteRule ^old-article\.html$ /new-article/ [R=301,L]
Массовый редирект целой директории:
RewriteRule ^blog/old-category/(.*)$ /blog/new-category/$1 [R=301,L]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?mysite\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,NC]
Вместо F можно подставить свою картинку-заглушку:
RewriteRule \.(jpg|jpeg|png|gif|webp)$ /images/no-hotlink.png [L]
RewriteCond %{HTTP_USER_AGENT} (AhrefsBot|SemrushBot|MJ12bot|DotBot) [NC]
RewriteRule ^ - [F,L]
Будьте аккуратны: некоторые боты приносят трафик. Блокируйте только тех, кто реально грузит сервер.
RewriteRule ^\.htaccess$ - [F]
RewriteRule ^\.git - [F]
RewriteRule ^(wp-config\.php|xmlrpc\.php) - [F]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z0-9-]+)/?$ /article.php?slug=$1 [L,QSA]
Условия !-f и !-d гарантируют, что правило не сломает существующие файлы и папки.
.php из URLRewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]
Теперь site.com/about откроет about.php.
ErrorDocument 404 /404.php
Или через RewriteRule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /404.php [L]

За годы практики я видел сотни сломанных сайтов из-за неправильных правил. Вот самые частые грабли.
Ошибка 1. Бесконечный цикл редиректов.
Симптом: браузер выдаёт ERR_TOO_MANY_REDIRECTS. Причина — правило редиректа срабатывает на уже перенаправленный URL.
Решение: добавляйте условие, проверяющее, что редирект ещё не сделан:
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Ошибка 2. Забытый флаг [L].
Без него сервер продолжит применять следующие правила, что приводит к непредсказуемым результатам. Почти всегда ставьте [L].
Ошибка 3. Неэкранированные точки в шаблоне.
^old-page.html$ — точка здесь означает «любой символ». Нужно писать ^old-page\.html$.
Ошибка 4. Конфликт с физическими файлами.
Если у вас есть папка /images/, а правило переписывает всё в /index.php, папка перестанет работать. Всегда добавляйте RewriteCond %{REQUEST_FILENAME} !-f и !-d.
Ошибка 5. Использование 302 вместо 301.
Для SEO критичен именно 301-й редирект. 302-й говорит поисковикам «это временно», и они не переносят вес страницы.
Ошибка 6. Потеря GET-параметров.
Если в исходном URL были параметры (?utm_source=...), без флага [QSA] они потеряются.
Никогда не пишите правила сразу на рабочем сайте. Последовательность такая:
.htaccess. Перед правками скачайте текущий файл.curl -I https://site.com/old-url — смотрите HTTP/1.1 301 Moved Permanently.mod_rewrite — тяжёлый модуль. Каждое правило — это проверка регулярного выражения на каждый запрос. Десяток правил — нормально. Сотня — уже проблема.
Советы по оптимизации:
[L] — сервер не будет гонять URL по оставшимся правилам.(a|b|c).RewriteMap — механизм, который подгружает таблицу соответствий из внешнего файла.Пример с RewriteMap:
RewriteMap redirects txt:/var/www/redirects.txt
RewriteCond ${redirects:$1} ^(.+)$
RewriteRule ^(.*)$ %1 [R=301,L]
В файле redirects.txt просто список:
old-page /new-page
another-old /another-new
Это работает в разы быстрее, чем сотни отдельных RewriteRule.
В популярных CMS файл .htaccess уже содержит базовые правила. Вот типичные блоки.
WordPress:
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Никогда не правьте этот блок вручную — WordPress его перезапишет. Свои правила добавляйте до # BEGIN WordPress.
1С-Битрикс:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$
RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
Здесь логика похожа, но используется urlrewrite.php, а настройки ЧПУ лежат в админке.
OpenCart:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

Некоторые правила выглядят безобидно, но открывают дыры.
Никогда не пишите:
RewriteRule ^(.*)$ /index.php?path=$1 [L,QSA]
Без проверки вы передаёте в скрипт что угодно, включая ../../etc/passwd.
Всегда валидируйте входные данные на уровне PHP, а не только в .htaccess.
Ограничьте доступ к админке по IP:
RewriteCond %{REMOTE_ADDR} !^123\.45\.67\.89$
RewriteRule ^admin/ - [F,L]
Перед тем как залить изменённый .htaccess на рабочий сайт, пройдите по пунктам:
[R=301,L]Не все задачи стоит решать через mod_rewrite. Если у вас Nginx — используйте его нативный rewrite. Если сайт на PHP и правила сложные — иногда проще обрабатывать роутинг в самом приложении (через $_SERVER['REQUEST_URI']).
Кроме того, есть мнение, что излишнее увлечение .htaccess замедляет сервер. Это правда, но для большинства проектов с десятком правил разница незаметна. Проблемы начинаются, когда в файле сотни строк.
Ещё один момент: на shared-хостингах вы не всегда можете менять основной конфиг Apache. Иногда AllowOverride стоит в None, и .htaccess просто игнорируется. В таком случае просите хостера включить AllowOverride All для вашей директории. Узнайте что такое поисковый запрос.
RewriteRule — это рабочий инструмент, а не магия. Поняв синтаксис, регулярные выражения и логику mod_rewrite, вы сможете решать 90% задач по управлению URL без привлечения программистов.
Главные мысли, которые стоит запомнить:
RewriteRule шаблон подстановка [флаги][R=301,L][QSA], если в URL могут быть GET-параметрыApache Mod Rewrite остаётся актуальным инструментом даже в эпоху Nginx и современных фреймворков — там, где нужен гибкий контроль на уровне веб-сервера, ему нет равных. Начните с простых редиректов, постепенно усложняйте правила, и через пару недель вы будете писать их так же уверенно, как обычные CSS-селекторы.
DeepSeek R2 — это новая генерация языковой модели от китайской лаборатории DeepSeek,...
