Академия mod_rewrite. Урок 2: флаги [R], [L], [QSA], [NC], [F], [G] и другие
Флаги RewriteRule управляют тем, что именно происходит после срабатывания правила: редирект или перезапись, постоянный или временный, сохранять ли строку запроса, блокировать ли доступ. В этом уроке разберём все ключевые флаги с примерами.
Урок 2 из 5 · ← предыдущий | следующий → · оглавление курса
Зачем нужны флаги
Флаги записываются в квадратных скобках через запятую после подстановки: RewriteRule паттерн подстановка [флаг1,флаг2]. Они определяют:
- тип ответа — внутренняя перезапись, редирект (и с каким кодом), блокировка;
- что делать со строкой запроса (
?param=value); - чувствительность к регистру и кодирование символов;
- поведение при цепочках правил.
Флаги редиректа: R=301, R=302, R=307, R=308
Флаг [R] превращает правило во внешний редирект — сервер отвечает кодом 30x и браузер переходит по новому адресу. Без числа — код 302 (временный).
[R=301]— постоянный редирект. Браузер и поисковики запоминают новый адрес. Используйте при переезде страниц навсегда.[R=302]— временный редирект. Поисковики продолжают индексировать старый адрес. Используйте для временных акций, A/B-тестов.[R=307]— временный, сохраняет метод запроса (POST остаётся POST). Для форм и API.[R=308]— постоянный, сохраняет метод запроса (Apache 2.4.26+).
Пример постоянного редиректа с сохранением пути:
RewriteEngine On RewriteRule ^old-section/(.*)$ /new-section/$1 [R=301,L]
Важно: подстановка при [R] должна быть абсолютным путём (начинаться с /) или полным URL. Относительная подстановка с [R] приводит к непредсказуемому результату.
[L] и [END]: остановить обработку
[L] — «last». Останавливает обработку правил в текущем проходе. Но в контексте .htaccess Apache перезапускает весь набор правил с новым URL, если он изменился. Поэтому [L] не гарантирует, что другие правила не применятся.
[END] — полная остановка (Apache 2.4+). Предотвращает перезапуск набора правил. Используйте, когда нужно гарантированно остановить обработку.
Типичная ошибка: правило с [L] делает внутреннюю перезапись, а ниже есть фронт-контроллер. После прохода Apache запускает набор заново и фронт-контроллер срабатывает на уже переписанный URL. Решение — правильный порядок правил или замена [L] на [END] там, где это уместно.
[QSA] и [QSD]: строка запроса
Строка запроса (?id=5&page=2) по умолчанию ведёт себя так: если в подстановке есть ? — она заменяет исходную строку запроса; если ? нет — исходная сохраняется.
[QSA] («query string append») — добавить исходную строку запроса к новой. Полезно, когда подстановка уже содержит параметры и нужно сохранить дополнительные:
RewriteEngine On RewriteRule ^product/(\d+)$ /catalog.php?id=$1 [L,QSA]
Запрос /product/42?color=red будет обработан как /catalog.php?id=42&color=red.
[QSD] («query string discard», Apache 2.4+) — отбросить исходную строку запроса. Полезно при редиректах на чистые URL.
[NC] и [NE]: регистр и кодирование
[NC] («nocase») — сопоставлять паттерн без учёта регистра. Например, паттерн ^image\.PNG$ с [NC] сработает и на image.png, и на image.PNG, и на IMAGE.Png.
Используйте осторожно: [NC] может «поглотить» больше запросов, чем вы планировали. Лучше явно указывать расширения в нижнем регистре и не полагаться на [NC] без необходимости.
[NE] («noescape») — не URL-кодировать спецсимволы в подстановке. Нужен, когда подстановка содержит символы ?, #, % и они должны остаться как есть, а не быть закодированы.
[F] и [G]: блокировка и Gone
[F] («forbidden») — вернуть ответ 403 Forbidden. Используется для блокировки доступа к файлам, каталогам, по User-Agent. Подстановку обычно пишут как - (не менять URL):
RewriteEngine On RewriteRule \.(sql|bak|log)$ - [F,L]
[G] («gone») — вернуть ответ 410 Gone. Означает «ресурс удалён навсегда». Поисковики, получив 410, быстрее убирают страницу из индекса, чем при 404. Используйте для намеренно удалённых страниц:
RewriteEngine On RewriteRule ^promo-2019/?$ - [G,L]
[C] и [S=N]: цепочки и пропуск
[C] («chain») — «сцепить» это правило со следующим. Следующее правило выполнится только если текущее сработало. Если текущее не сработало — следующее (и вся цепочка) пропускается. Полезно для последовательных преобразований.
[S=N] («skip») — при срабатывании правила пропустить следующие N правил. Это что-то вроде goto: позволяет реализовать ветвление без лишних условий.
RewriteEngine On # Если файл существует — пропустить 1 следующее правило RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^ - [S=1] # Это правило сработает только если файл НЕ существует RewriteRule ^ index.php [L]
Попробуй сам
Откройте тестер RewriteRule и поэкспериментируйте с флагами: попробуйте добавить и убрать [QSA], заменить [R=301] на [R=302], посмотреть разницу в трассировке. Особенно полезно сравнить поведение с [L] и без него.
Упражнения
-
Напишите временный редирект (302) со старого раздела
/promo/на/sales/.
Подсказка:[R=302,L]или просто[R,L]— по умолчанию 302.
Проверьте в тестере RewriteRule. -
Напишите правило с
[QSA]: перезаписать/item/5в/item.php?id=5, при этом сохранив любые дополнительные параметры вроде?color=red.
Подсказка: используйте группу захвата(\d+)для числа.
Проверьте в тестере RewriteRule. -
Вернуть
410 Goneна запросы к/promo-2019и/promo-2020.
Подсказка: паттерн с альтернативой(2019|2020)и флаг[G,L].
Проверьте в тестере RewriteRule. -
Почему флаг
[NC]иногда опасен? Приведите пример ситуации, когда он может захватить лишнее.
Подсказка: паттерн^adminс[NC]сработает и на/Admin, и на/ADMIN.
Что дальше
В уроке 3 разберём RewriteCond — условия перед правилом, серверные переменные %{HTTP_HOST}, %{HTTPS}, %{REQUEST_URI} и специальные проверки файловой системы. Именно там живёт настоящая мощь mod_rewrite.