Флаги RewriteRule
В данном документе обсуждаются флаги, доступные для директивы RewriteRule, с подробными объяснениями и примерами.
Введение
Поведение RewriteRule может быть изменено одним или несколькими флагами. Флаги включаются в квадратные скобки в конце правила, а несколько флагов разделяются запятыми.
RewriteRule pattern target [Flag1,Flag2,Flag3]
Каждый флаг (за некоторыми исключениями) имеет короткую форму, например CO, а также длинную форму, например cookie. Хотя чаще используется короткая форма, рекомендуется ознакомиться с длинной формой, чтобы запомнить назначение каждого флага. Некоторые флаги принимают один или несколько аргументов. Флаги не чувствительны к регистру.
Флаги, которые изменяют метаданные, связанные с запросом (T=, H=, E=) не имеют эффекта в контексте каталога и .htaccess, когда выполняется замена (кроме '-') в ходе одной и той же обработки переписывания.
Ниже приведены все доступные флаги, а также примеры их использования.
B (экранирование обратных ссылок)
Флаг [B] инструктирует RewriteRule экранировать небуквенно-цифровые символы перед применением преобразования.
В 2.4.26 и более поздних версиях можно ограничить экранирование определенными символами в обратных ссылках, перечислив их: [B=#?;]. Примечание: пробел может использоваться в списке экранируемых символов, но не может быть последним символом в списке.
mod_rewrite должен расшифровать URL перед их отображением, поэтому обратные ссылки расшифровываются в момент их применения. Используя флаг B, небуквенно-цифровые символы в обратных ссылках будут экранированы. Например, рассмотрим правило:
RewriteRule "^search/(.*)$" "/search.php?term=$1"
Если в запросе используется термин 'x & y/z', браузер закодирует его как 'x%20%26%20y%2Fz', что создаст запрос 'search/x%20%26%20y%2Fz'. Без флага B это правило переписывания будет отображать 'search.php?term=x & y/z', что не является валидным URL, и поэтому будет закодировано как search.php?term=x%20&y%2Fz=, что не соответствует задумке.
С флагом B установленном в этом же правиле, параметры повторно кодируются перед передачей в выходной URL, что приводит к правильному отображению /search.php?term=x%20%26%20y%2Fz.
RewriteRule "^search/(.*)$" "/search.php?term=$1" [B,PT]
Обратите внимание, что также может потребоваться установить AllowEncodedSlashes на On для работы данного примера, так как httpd не допускает закодированных слешей в URL и возвращает 404, если их видит.
Это экранирование особенно необходимо в ситуации с прокси, когда бэкенд может выйти из строя, если ему будет представлен неэкранированный URL.
Альтернативой этому флагу является использование RewriteCond для захвата данных в %{THE_REQUEST}, который захватывает строки в закодированном виде.
BNP|backrefnoplus (не экранировать пробел в +)
Флаг [BNP] инструктирует RewriteRule экранировать пробел в обратной ссылке как %20, а не '+'. Полезно, когда обратная ссылка будет использоваться в компоненте пути, а не в строке запроса.
Этот флаг доступен в версии 2.4.26 и более поздних.
C|chain
Флаг [C] или [chain] указывает на то, что RewriteRule привязано к следующему правилу. То есть, если правило соответствует, оно обрабатывается как обычно, и управление передаётся следующему правилу. Однако, если правило не соответствует, следующее правило и любые другие привязанные к нему правила пропускаются.
CO|cookie
Флаг [CO] или [cookie] позволяет установить cookie, когда конкретное RewriteRule соответствует шаблону. Аргумент состоит из трёх обязательных и пяти необязательных полей.
Полный синтаксис флага, включая все атрибуты, представлен ниже:
[CO=NAME:VALUE:DOMAIN:lifetime:path:secure:httponly:samesite]Если в любом из полей cookie требуется символ ':' в прямом виде, доступен альтернативный синтаксис. Для включения альтернативного синтаксиса имя cookie должно быть предваряться символом ';', а разделители полей должны быть указаны как ';'.
[CO=;NAME;VALUE:MOREVALUE;DOMAIN;lifetime;path;secure;httponly;samesite]Вы должны объявить имя, значение и домен для установки cookie.
- Домен
- Домен, для которого должно быть валидно cookie. Это может быть имя хоста, например
www.example.com, или домен, например.example.com. Домен должен состоять как минимум из двух частей, разделённых точкой. То есть, он не может быть просто.comили.net. Cookie такого рода запрещены моделью безопасности cookie.
Вы можете необязательно также установить следующие значения:
- Срок действия
- Время, в минутах, на протяжении которого cookie будет сохраняться.
- Значение 0 указывает, что cookie будет храниться только для текущей сессии браузера. Это значение по умолчанию, если оно не указано.
- Путь
- Путь на текущем веб-сайте, для которого cookie является валидным, например
/customers/или/files/download/. - По умолчанию это установлено на
/— весь веб-сайт. - Защищённый
- Если установлено
secure,true, или1, cookie будет разрешено передавать только по защищённым (https) соединениям. - httponly
- Если установлено
HttpOnly,true, или1, для cookie будет установлен флагHttpOnly, что означает, что cookie недоступен для кода JavaScript в браузерах, поддерживающих эту функцию. - samesite
- Если установлено значение отличное от
falseили0, то атрибутSameSiteустанавливается в указанное значение. Типичные значения —None,Lax, иStrict. Доступно в 2.5.1 и более поздних версиях.
Рассмотрим этот пример:
RewriteEngine On RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.com:1440:/]
В данном примере правило не переписывает запрос. Цель переписывания «-» указывает mod_rewrite на передачу запроса без изменений. Вместо этого, устанавливается cookie с именем 'frontdoor' со значением 'yes'. Cookie валиден для любого хоста в домене .example.com . Срок истечения cookie установлен на 1440 минут (24 часа) и он возвращается для всех URI.
DPI|discardpath
Флаг DPI приводит к тому, что часть PATH_INFO переписанного URI отбрасывается.
Этот флаг доступен в версии 2.2.12 и более поздних.
В контексте каталога каждый RewriteRule сравнивается с конкатенацией текущих значений URI и PATH_INFO.
Текущий URI может быть начальным URI, запрошенным клиентом, результатом предыдущей обработки mod_rewrite или результатом обработки предыдущего правила в текущем цикле обработки mod_rewrite.
В отличие от этого, PATH_INFO, который добавляется к URI перед каждым правилом, отражает только значение PATH_INFO до текущего цикла обработки mod_rewrite. В результате, если большие части URI сопоставляются и копируются в подстановку в нескольких директивах RewriteRule , без учёта того, какие части URI пришли из текущего PATH_INFO, конечный URI может иметь несколько копий PATH_INFO, присоединённых к нему.
Используйте этот флаг в любой замене, где PATH_INFO, полученный в результате предыдущей сопоставления этого запроса с файловой системой, не нужен. Этот флаг навсегда забывает PATH_INFO, установленный перед началом текущего цикла обработки mod_rewrite. PATH_INFO не будет пересчитан, пока не завершится текущий цикл обработки mod_rewrite. Последующие правила в этом цикле обработки увидят только прямой результат подстановок, без добавления PATH_INFO.
E|env
С флагом [E] или [env] можно установить значение переменной среды. Обратите внимание, что некоторые переменные среды могут быть установлены после выполнения правила, тем самым отменив ранее установленное значение. Подробную информацию о работе переменных среды см. в документе Переменные среды.
Полный синтаксис этого флага:
[E=VAR:VAL] [E=!VAR]
VAL может содержать обратные ссылки ($N или %N ), которые будут расширены.
Используя короткую форму
[E=VAR]можно установить переменную среды с именем VAR в пустое значение.
Форма
[E=!VAR]позволяет сбросить ранее установленную переменную среды с именем VAR.
Переменные среды могут использоваться в различных контекстах, включая программы CGI, другие директивы RewriteRule или директивы CustomLog.
Следующий пример устанавливает переменную среды 'image' в значение '1', если запрашиваемый URI — это файл изображения. Затем эта переменная среды используется для исключения этих запросов из журнала доступа.
RewriteRule "\.(png|gif|jpg)$" "-" [E=image:1] CustomLog "logs/access_log" combined env=!image
Обратите внимание, что тот же эффект можно получить с помощью SetEnvIf. Этот метод приводится в качестве примера, а не рекомендации.
END
Использование флага [END] завершает не только текущий цикл обработки переписывания (как [L]), но и предотвращает последующую обработку переписывания в контексте каталога (htaccess).
Это не относится к новым запросам, полученным в результате внешних перенаправлений.
F|forbidden
Использование флага [F] заставляет сервер возвращать клиенту код состояния 403 Forbidden. Хотя тот же эффект можно получить с помощью директивы Deny, это даёт больше гибкости в назначении состояния Forbidden.
Следующее правило запрещает загрузку файлов .exe с вашего сервера.
RewriteRule "\.exe" "-" [F]
В этом примере используется синтаксис «-» для цели переписывания, что означает, что запрашиваемый URI не изменяется. Нет смысла переписывать URI на другой, если вы собираетесь запретить запрос.
При использовании [F] подразумевается [L] — ответ возвращается немедленно, и дальнейшие правила не оцениваются.
G|gone
Флаг [G] заставляет сервер возвращать код состояния 410 Gone в ответе. Это указывает на то, что ресурс ранее был доступен, но теперь недоступен.
Как и с флагом [F], вы обычно используете синтаксис «-» для цели переписывания при использовании флага [G]:
RewriteRule "oldproduct" "-" [G,NC]
При использовании [G] подразумевается [L] — ответ возвращается немедленно, и дальнейшие правила не оцениваются.
H|handler
Принудительно обрабатывает полученный запрос с указанным обработчиком. Например, можно принудительно обрабатывать все файлы без расширения с помощью обработчика php:
RewriteRule "!\." "-" [H=application/x-httpd-php]
Вышеприведённое регулярное выражение - !\. - будет соответствовать любому запросу, не содержащему символ ..
Это также может быть использовано для принудительного назначения обработчика на основе некоторых условий. Например, следующий фрагмент кода, используемый в контексте сервера, позволяет отображать файлы .php с помощью mod_php , если они запрошены с расширением .phps:
RewriteRule "^(/source/.+\.php)s$" "$1" [H=application/x-httpd-php-source]
Вышеприведённое регулярное выражение - ^(/source/.+\.php)s$ - будет соответствовать любому запросу, начинающемуся с /source/ , за которым следуют 1 или более символов, и затем буквально .phps . Обратная ссылка $1 относится к захваченному совпадению внутри скобок регулярного выражения.
L|last
Флаг [L] вызывает mod_rewrite прекратить обработку набора правил. В большинстве контекстов это означает, что если правило совпадает, дальнейшая обработка правил не будет производиться. Это соответствует команде last в Perl или команде break в C. Используйте этот флаг для указания на то, что текущее правило должно быть применено немедленно, без учета дальнейших правил.
Если вы используете RewriteRule в файлах .htaccess или в разделах <Directory>, важно понимать, как обрабатываются правила. Упрощенно, после обработки правил переписанный запрос передается обратно модулю парсинга URL для дальнейшей обработки. Возможны ситуации, когда при обработке переписанного запроса могут быть повторно встречены файл .htaccess или раздел <Directory>, и в таком случае набор правил может быть запущен повторно с самого начала. Чаще всего это происходит, если одно из правил вызывает переадресацию — внутреннюю или внешнюю — из-за чего процесс запроса начинается заново.
Поэтому важно, если вы используете директивы RewriteRule в одном из этих контекстов, принять явные меры, чтобы избежать циклов правил, а не полагаться только на флаг [L] для прекращения выполнения серии правил, как показано ниже.
Альтернативный флаг [END] может быть использован для прекращения не только текущего раунда обработки переписывания, но и предотвращения любой последующей обработки переписывания в контексте каталога (htaccess). Это не относится к новым запросам, полученным в результате внешних переадресаций.
Приведенный пример перепишет любой запрос на index.php, передав исходный запрос в качестве аргумента строки запроса к index.php, однако RewriteCond гарантирует, что если запрос уже предназначен для index.php, то RewriteRule будет пропущено.
RewriteBase "/"
RewriteCond "%{REQUEST_URI}" "!=/index.php"
RewriteRule "^(.*)" "/index.php?req=$1" [L,PT] N|next
Флаг [N] заставляет набор правил начать заново с начала, используя результат обработки набора правил до этого момента в качестве отправной точки. Используйте с большой осторожностью, так как это может привести к циклу.
Флаг [Next] может быть использован, например, если вам нужно повторно заменить определенную строку или символ в запросе. Приведенный здесь пример заменит A на B во всем запросе и будет продолжать делать это до тех пор, пока не будут заменены все A.
RewriteRule "(.*)A(.*)" "$1B$2" [N]
Можно рассматривать это как цикл while: пока этот шаблон соответствует (т.е. пока в URI содержится A), выполните это подстановку (т.е. замените A на B).
В версиях 2.4.8 и более поздних эта модуль возвращает ошибку после 32 000 итераций, чтобы защитить от непреднамеренных циклов. Максимальное количество итераций можно указать, добавив его к флагу N.
# Be willing to replace 1 character in each pass of the loop RewriteRule "(.+)[><;]$" "$1" [N=64000] # ... or, give up if after 10 loops RewriteRule "(.+)[><;]$" "$1" [N=10]
NC|nocase
Использование флага [NC] приводит к тому, что RewriteRule сопоставляется без учета регистра. То есть, регистр букв в сопоставляемом URI не имеет значения.
В примере ниже любой запрос на файл изображения будет перенаправлен на ваш выделенный сервер изображений. Сопоставление производится без учета регистра, поэтому .jpg и .JPG файлы будут приемлемы.
RewriteRule "(.*\.(jpg|gif|png))$" "http://images.example.com$1" [P,NC]
NE|noescape
По умолчанию специальные символы, такие как & и ?, например, будут преобразованы в их шестнадцатеричный эквивалент. Использование флага [NE] предотвращает это.
RewriteRule "^/anchor/(.+)" "/bigpage.html#$1" [NE,R]
В приведенном выше примере /anchor/xyz будет перенаправлен на /bigpage.html#xyz. Опускание флага [NE] приведет к тому, что символ # будет преобразован в его шестнадцатеричный эквивалент %23, что в результате приведет к ошибке 404 Not Found.
NS|nosubreq
Использование флага [NS] предотвращает применение правила к подзапросам. Например, страница, включенная с помощью SSI (Server Side Include), является подзапросом, и вы можете захотеть избежать переписывания при таких подзапросах. Также, когда mod_dir пытается найти информацию о возможных файлах по умолчанию для каталога (например, index.html файлы), это внутренний подзапрос, и вы часто хотите избежать переписывания при таких подзапросах. При подзапросах полное применение набора правил не всегда полезно и даже может привести к ошибкам. Используйте этот флаг, чтобы исключить проблемные правила.
Чтобы решить, использовать ли это правило: если вы добавляете префиксы к URL-адресам с CGI-скриптами, чтобы принудительно заставить их обрабатываться CGI-скриптом, скорее всего, у вас возникнут проблемы (или значительные накладные расходы) при подзапросах. В этих случаях используйте этот флаг.
Изображения, файлы javascript или css, загруженные как часть HTML-страницы, не являются подзапросами — браузер запрашивает их как отдельные HTTP-запросы.
P|proxy
Использование флага [P] приводит к обработке запроса mod_proxy, и обработке через запрос-прокси. Например, если вы хотите, чтобы все запросы на изображения обрабатывались сервером изображений бэкенда, вы можете сделать следующее:
RewriteRule "/(.*)\.(jpg|gif|png)$" "http://images.example.com/$1.$2" [P]
Использование флага [P] подразумевает [L] — запрос сразу же направляется через прокси, и последующие правила не будут рассматриваться.
Вы должны убедиться, что строка подстановки является допустимым URI (обычно начинающимся с http://hostname), который может обрабатываться mod_proxy. В противном случае модуль прокси вернёт ошибку. Используйте этот флаг для достижения более мощной реализации директивы ProxyPass, для отображения удаленного содержимого в пространстве имён локального сервера.
Предупреждение о безопасности
Будьте внимательны при построении целевого URL-адреса правила, учитывая последствия безопасности, позволяющие клиенту влиять на набор URL-адресов, по которым ваш сервер будет действовать как прокси. Убедитесь, что схема и имя хоста URL-адреса либо фиксированы, либо не позволяют клиенту оказывать чрезмерное влияние.
Предупреждение об производительности
Использование этого флага запускает использование mod_proxy, без обработки постоянных соединений. Это означает, что производительность вашего прокси будет лучше, если вы настроите его с использованием ProxyPass или ProxyPassMatch
Это происходит потому, что этот флаг запускает использование стандартного работника, который не обрабатывает пулы/повторное использование соединений.
Избегайте использования этого флага и отдавайте предпочтение этим директивам, когда это возможно.
Примечание: mod_proxy должен быть включён для использования этого флага.
PT|passthrough
По умолчанию целевой объект (или строка подстановки) в RewriteRule предполагается файловым путем. Использование флага [PT] заставляет его обрабатываться как URI вместо этого. То есть использование флага [PT] приводит к тому, что результат RewriteRule передается обратно через сопоставление URL-адресов, так что основанные на местоположении сопоставления, такие как Alias, Redirect, или ScriptAlias, например, могут иметь шанс сработать.
Если, например, у вас есть Alias для /icons, и у вас есть RewriteRule указывающий на него, вы должны использовать флаг [PT], чтобы убедиться, что Alias был оценен.
Alias "/icons" "/usr/local/apache/icons" RewriteRule "/pics/(.+)\.jpg$" "/icons/$1.gif" [PT]
Пропуск флага [PT] в этом случае приведет к игнорированию Alias и возвращению ошибки 'Файл не найден'.
Флаг PT подразумевает флаг L: переписывание будет остановлено для передачи запроса на следующую фазу обработки.
Обратите внимание, что флаг PT подразумевается в контекстах каталога, таких как разделы <Directory> или в файлах .htaccess. Единственный способ обойти это — переписать на -.
QSA|qsappend
Когда целевой URI содержит строку запроса, по умолчанию RewriteRule отбрасывает существующую строку запроса и заменяет её новой. Использование флага [QSA] приводит к объединению строк запроса.
Рассмотрим следующее правило:
RewriteRule "/pages/(.+)" "/page.php?page=$1" [QSA]
С флагом [QSA] запрос на /pages/123?one=two будет сопоставлен с /page.php?page=123&one=two. Без флага [QSA] тот же запрос будет сопоставлен с /page.php?page=123 — существующая строка запроса будет отброшена.
QSD|qsdiscard
Когда запрашиваемый URI содержит строку запроса, а целевой URI нет, по умолчанию RewriteRule копирует эту строку запроса в целевой URI. Использование флага [QSD] приводит к отбрасыванию строки запроса.
Этот флаг доступен в версии 2.4.0 и более поздних.
Использование [QSD] и [QSA] вместе приведёт к тому, что [QSD] будет иметь приоритет.
Если целевой URI имеет строку запроса, будет наблюдаться стандартное поведение — оригинальная строка запроса будет отброшена и заменена строкой запроса в целевом URI RewriteRule.
QSL|qslast
По умолчанию первая (самая левая) точка вопроса в строке подстановки определяет разделитель пути и строки запроса. Использование флага [QSL] указывает RewriteRule разделить эти две компоненты с помощью последней (правой) точки вопроса.
Это полезно при сопоставлении с файлами, в имени которых есть буквальные вопросительные знаки. Если в строке замены нет строки запроса, то с помощью этого флага к ней можно добавить вопросительный знак.
Этот флаг доступен в версии 2.4.19 и более поздних.
R|redirect
Использование флага [R] вызывает переадресацию HTTP-запроса в браузере. Если указан полностью квалифицированный URL (т.е. включающий http://servername/), то переадресация будет выполнена на этот адрес. В противном случае текущий протокол, имя сервера и номер порта будут использованы для создания отправляемого URL-адреса.
Любой допустимый HTTP-код ответа может быть указан, используя синтаксис [R=305], при этом код ответа 302 используется по умолчанию, если не указан другой. Код ответа, указанный явно, не обязательно должен быть кодом переадресации (3xx). Однако, если код ответа находится вне диапазона переадресации (300-399), строка подстановки полностью отбрасывается, и переписывание останавливается так же, как если бы был использован флаг L.
В дополнение к кодам ответов вы также можете указать код переадресации с использованием их символических имён: temp (по умолчанию), permanent, или seeother.
Вы почти всегда захотите использовать [R] в сочетании с [L] (т.е. использовать [R,L]), потому что сам по себе флаг [R] добавляет http://thishost[:thisport] к URI, но затем передает его следующему правилу в наборе правил, что часто приводит к предупреждениям 'Неверный URI в запросе'.
S|skip
Флаг [S] используется для пропуска правил, которые вы не хотите запускать. Синтаксис флага пропуска — [S=N], где N обозначает количество правил для пропуска (при условии, что RewriteRule соответствует). Это можно представить как оператор goto в вашем наборе правил переписывания. В следующем примере мы хотим запустить RewriteRule только если запрашиваемый URI не соответствует фактическому файлу.
# Is the request for a non-existent file?
RewriteCond "%{REQUEST_FILENAME}" "!-f"
RewriteCond "%{REQUEST_FILENAME}" "!-d"
# If so, skip these two RewriteRules
RewriteRule ".?" "-" [S=2]
RewriteRule "(.*\.gif)" "images.php?$1"
RewriteRule "(.*\.html)" "docs.php?$1" Этот метод полезен, потому что RewriteCond применяется только к RewriteRule, непосредственно следующему за ним. Таким образом, если вы хотите, чтобы RewriteCond применялось к нескольким RewriteRule, одним из возможных методов является отрицание этих условий и добавление RewriteRule с флагом [Skip]. Это позволяет создавать псевдоконструкции if-then-else: Последнее правило в части then становится skip=N, где N — количество правил в части else:
# Does the file exist?
RewriteCond "%{REQUEST_FILENAME}" "!-f"
RewriteCond "%{REQUEST_FILENAME}" "!-d"
# Create an if-then-else construct by skipping 3 lines if we meant to go to the "else" stanza.
RewriteRule ".?" "-" [S=3]
# IF the file exists, then:
RewriteRule "(.*\.gif)" "images.php?$1"
RewriteRule "(.*\.html)" "docs.php?$1"
# Skip past the "else" stanza.
RewriteRule ".?" "-" [S=1]
# ELSE...
RewriteRule "(.*)" "404.php?file=$1"
# END Вероятно, эту конфигурацию проще реализовать с помощью директив <If>, <ElseIf> и <Else>.
T|тип
Устанавливает тип MIME, с которым будет отправляться результирующий ответ. Это имеет тот же эффект, что и директива AddType.
Например, можно использовать следующий метод для предоставления исходного кода Perl как простого текста, если это запрошено определённым образом:
# Serve .pl files as plain text RewriteRule "\.pl$" "-" [T=text/plain]
Или, возможно, если у вас есть камера, которая генерирует изображения jpeg без расширений файлов, вы можете принудительно задать правильный тип MIME для этих изображений благодаря их именам файлов:
# Files with 'IMG' in the name are jpg images. RewriteRule "IMG" "-" [T=image/jpg]
Обратите внимание, что это тривиальный пример и его можно было бы сделать лучше, используя <FilesMatch> вместо этого. Всегда следует рассматривать альтернативные решения проблемы, прежде чем прибегать к переписыванию, которое неизбежно будет менее эффективным решением, чем альтернативные варианты.
При использовании в контексте каталога, используйте только - (тире) в качестве подстановки для всего цикла обработки mod_rewrite, в противном случае тип MIME, установленный с этим флагом, теряется из-за внутренней повторной обработки (включая последующие циклы обработки mod_rewrite). Флаг L может быть полезен в этом контексте, чтобы завершить текущий цикл обработки mod_rewrite.
© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/rewrite/flags.html