Полное руководство по mod_rewrite (часть 3): Флаги RewriteRule


Оглавление. Полное руководство по mod_rewrite

1. Как включить и как работает mod_rewrite

2. Регулярные выражения mod_rewrite

3. Флаги RewriteRule

3.1 F|Forbidden – Запрет доступа, возвращает браузеру клиента ответ 403 FORBIDDEN

3.2 NC|nocase – Выполнять сравнение без учёта регистра

3.3 R|redirect – Выполнить редирект (перенаправление)

3.4 L|last – Последнее правило (остановка текущего цикла)

3.5 END – Немедленная остановка процесса перезаписи

3.6 H|handler – Отправка результирующего URI указанному Content-handler для обработки

3.7 C|chain – Составление цепи из правил

3.8 N|next – Перезапуск процесс перезаписи начиная с первого правила

3.9 QSA|qsappend – Добавить строку запроса из исходного URL к строке запроса, созданной правилами перезаписи

3.10 QSD|qsdiscard – Отбросить любую строку запроса из входящего URI

3.11 QSL|qslast – Сделать разделителем строки самый правый знак вопроса

3.12 NE|noescape – Не экранировать специальные символы в результатах

3.13 NS|nosubreq – Пропуск правила, если текущий запрос является внутренним подзапросом

3.14 S|skip – Пропустить следующее количество правил, если сработало текущее правило

3.15 T|type – Принудительная установка MIME-типа целевого файла на указанный тип

3.16 B (экранировать обратные ссылки) – Экранировать не-буквенно-цифровые символы в обратных ссылках перед применения трансформации

3.17 BNP|backrefnoplus (не экранировать пробелы на +) – Если обратные ссылки будут экранированы, пробелы должны быть экранированы в %20 вместо +


3.18 CO|cookie – Устанавливает куки в клиентский браузер

3.19 DPI|discardpath – Приводит к отбрасыванию части PATH_INFO переписанного URI

3.20 E|env – Устанавливает или удаляет значение переменной окружения

3.21 G|gone – Возвращает клиентскому браузеру ответ 410 GONE

3.22 P|proxy – Заставляет URL-адрес подстановки быть внутренне отправленным в качестве прокси-запроса

3.23 PT|passthrough – Заставляет результирующий URI быть переданным обратно в механизм сопоставления URL-адресов для обработки другими URI-на-имя_файла трансляторами, таких как Alias или Redirect

4. Директива RewriteCond

5. Частые случаи и примеры использования mod_rewrite

6. Продвинутые техники

7. Директива RewriteMap

8. Директива RewriteOptions, технические подробности, когда НЕ использовать mod_rewrite


Как мы помним, RewriteRule имеет следующий синтаксис использования:

RewriteRule Шаблон Подстановка [флаги]

Флаги изменяют поведение RewriteRule, можно указать один или более флагов для правила преобразования. Флаги пишутся в квадратных скобках на конце правила, если используется несколько флагов, то они разделяются запятой.

RewriteRule Шаблон Подстановка [Флаг1,Флаг2,Флаг3]

Каждый флаг (за редким исключением) имеет краткую форму, такую как CO, а также полную форму, такую как cookie. Хотя чаще используют короткие формы, не будет лишним ознакомиться и с полной формой, чтобы вы знали о их существовании. Некоторые флаги принимают один или более аргументов. Флаги не чувствительны к регистру.

F|Forbidden – Запрет доступа, возвращает браузеру клиента ответ 403 FORBIDDEN

Флаг [F] или [Forbidden] приводит к тому, что сервер возвращает клиенту код статуса 403 Forbidden. Хотя такого же поведения можно достичь, используя директивы Require или Deny, этот флаг RewriteRule позволяет более гибко настроить доступ и выбрать ресурсы, для которых доступ запрещён.


Следующее правило запретит скачивание .exe файлов с вашего сервера:

RewriteRule "\.exe" "-" [F]

Этот пример использует синтаксис "" в качестве перезаписываемой цели, это означает, что запрашиваемый URI не модифицируется. Не имеет смысла перезаписывать исходный запрос на другой URI, если мы собираемся запретить запрос.

Запишем в файл .htaccess:

RewriteEngine on
RewriteRule dogs "-" [F]

В результате любые адреса, содержащие последовательность символов dogs будет заблокированы для входа, к примеру http://localhost/mr/dogs или http://localhost/mr/dogsandcats

При использовании [F], флаг [L] подразумевается — то есть ответ возвращается немедленно, и другие оценка по другим правилам не происходит.

NC|nocase – Выполнять сравнение без учёта регистра

Использование флага [NC] приводит к тому, что RewriteRule ищет совпадение без учёта регистра букв. Т.е. не имеет значение, большие или маленькие буквы используются в URI.

К примеру, если в файле .htaccess записано:

RewriteEngine on
RewriteRule dogs index.html

И в браузере мы открываем адрес http://localhost/mr/DOGS, то совпадение не будет найдено:

Если же мы добавим флаг [NC]:

RewriteEngine on
RewriteRule dogs index.html [NC]

То строка DOGS будет считаться совпадающей с шаблоном dogs.

R|redirect – Выполнить редирект (перенаправление)

Как вы могли заметить, пользователя не перебрасывает на новую страницу – ему просто показывается содержание этой новой страницы. Если вы хотите, чтобы происходило именно перенаправление, то используйте флаг редиректа [R]:

RewriteEngine on
RewriteBase /mr/
RewriteRule dogs index.html [R]

Мы использовали директиву RewriteBase.


Теперь если в браузере открыть http://localhost/mr/dogs, то пользователь будет перенаправлен на другую страницу и в строке браузера будет адрес http://localhost/mr/index.html

Если в качестве цели переадресации указан сайт вместе с протоколом (HTTP или HTTPS), то флаг [R] подразумевается автоматически и писать его необязательно. Следовательно следующий вариант:

RewriteEngine on
RewriteRule dogs https://mi-al.ru

И этот означают одно и то же:

RewriteEngine on
RewriteRule dogs https://mi-al.ru [R]

Используя синтаксис [R=305], можно указать любой действительный код статуса ответа HTTP. Если ничего не указано, то по умолчанию используется код статуса 302. Указываемый код статус не обязательно должен быть кодом статуса редиректа (3xx). Тем не менее, если код статуса за пределами диапазона редиректа (300-399), тогда строка подстановки полностью отбрасывается и перезапись останавливается, будто бы используется флаг L.

Т.е. такая запись:

RewriteEngine on
RewriteRule dogs https://mi-al.ru [R=404]

Не приведёт к перенаправлению на сайт mi-al.ru, вместо этого будет выведено сообщение об ошибке «не найдено»:

Кстати, вместо кодов статуса ответа, можно указать статус редиректа используя символические имена: temp (по умолчанию), permanent или seeother.

L|last – Последнее правило (остановка текущего цикла)

Прежде чем обсудить этот флаг, мы рассмотрим очень важный вопрос – как именно работает mod_rewrite. Правила директив RewriteRule выполняются последовательно. И даже если найдено одно совпадение, то продолжается проверка по другим правилам и если в последующих правилах также найдено совпадение, то каждый раз выполняется новая подстановка.

В нашей папке для тестов существует файл index.html, но не существует файлов dogs и cats. Протестируем следующий набор правил:

RewriteEngine on
RewriteRule dogs cats
RewriteRule cats index.html

Если в браузере мы открываем адрес http://localhost/mr/dogs, то мы видим содержимое файла index.html. Это кажется логичным, наша строка в первом правиле заменяется с dogs на cats, затем выполняется переход ко второму правилу, где заменяется cats на index.html. Файл index.html действительно присутствует в системе, и он показывается пользователю.

Переставим правила местами:

RewriteEngine on
RewriteRule cats index.html
RewriteRule dogs cats

Предположим, мы вновь открыть адрес http://localhost/mr/dogs, что произойдёт? Логика подсказывает, что первое правило будет пропущено, а во втором будет сделана замена dogs на cats. Поскольку файл cats отсутствует, то будет выведено сообщение об ошибке 404 – файл не найден. Но на самом деле:

Т.е. показывается содержимое файла index.html!

Это может показаться нелогичным или какой-то ошибкой. Но именно так работает mod_rewrite: если за данный проход было найдено хотя бы одно совпадение, то результирующая строка ещё раз отправляется на новый проход для проверки на совпадение по всем правилам!

В результате мы имеем, что при первом проходе, правило RewriteRule cats index.html пропущено, но срабатывает второе правило и dogs меняется на cats. Поскольку было найдено совпадение, то mod_rewrite заходит на новый круг, в результате которого первое правило меняет cats на index.html, второе правило пропускается, т.к. нет совпадений. На самом деле, mod_rewrite заходит ещё и на третий круг (поскольку во время второго случилось совпадение) – но в этом раунде не происходит ничего важного – ни одного совпадения, поэтому в результате пользователю показывается index.html.

И теперь можно разобраться, что именно делает флаг [L].

По умолчанию, обработка осуществляется по всем указанным правилам, даже если ранее уже было совпадение. Флаг [L] приводит к тому, что mod_rewrite останавливает обработку набора правил. Это означает, что если правило с флагом [L] совпадает, то другие правила больше не будут обрабатываться. Использование этого флага сигнализирует, что данное правило должно быть применено немедленно, без рассмотрения дальнейших правил.

Ещё раз более простым языком: флаг [L] останавливает рассмотрение дальнейших правил в данном цикле, НО НЕ ОТМЕНЯЕТ ПОСЛЕДУЮЩИЕ ЦИКЛЫ.

К примеру, имеется набор правил:

RewriteEngine on
RewriteRule cats index.html
RewriteRule dogs cats
RewriteRule cats beavers

Если мы откроем ссылку http://localhost/mr/dogs, то в первом проходе dogs будет заменено на cats, а cats заменено на beavers. При втором проходе больше совпадений не случиться, в результате пользователю будет показана страница beavers (которой нет, поэтому будет ошибка 404).

Если мы добавим флаг [L]:

RewriteEngine on
RewriteRule cats index.html
RewriteRule dogs cats [L]
RewriteRule cats beavers

То при открытии ссылки http://localhost/mr/dogs, мы увидим содержимое страницы index.html. Механизм следующий: при первом проходе dogs заменяется на cats и из-за флага [L] данный цикл завершается – последующие правила не рассматриваются, сразу происходит заход на следующий раунд. В результате следующего прохода, cats меняется на index.html. Больше никаких совпадений не происходит, в результате показывается index.html.

По умолчанию, если в предыдущую итерацию найдено совпадение, то mod_rewrite проходит 10 дополнительных итераций.

Вам кажется, что вы разобрались как работает mod_rewrite? Тогда головоломка с флагом [L]:

Следующие правила:

RewriteRule ^a.html$ b.html [L]
RewriteRule ^b.html$ a.html [L]

При запросе страницы a.html выдадут ошибку 500, бесконечный цикл.

В логах Apache будет запись с упоминанием директивы LimitInternalRecursion:

[Fri Apr 24 12:06:47.124897 2020] [core:error] [pid 2700:tid 1236] [client ::1:49782] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

Это логично, поскольку постоянно выполняется переадресация с одной страницы на другую.

Но следующие правила:

RewriteRule ^a.html$ b.html
RewriteRule ^b.html$ a.html

не выведут ошибку 500, а покажут просто сообщение, что файл a.html не найден (404)!

Разгадка этой головоломки: в результате выполнения всех RewriteRule запрос меняется таким образом, что конечный результат равен исходному. Apache видит это и не запускает повторную обработку запроса. Будет возвращён файл a.html.

Из этого нужно сделать следующий вывод: если после обработки правилами mod_rewrite получается точно такой же результат как и на входе, то Apache считает, что совпадения в правилах не было и новая итерация не начинается!

Флаг [L] и вообще многоцикличный механизм работы mod_rewrite очень плохо документированы – надеюсь, мне удалось восполнить этот пробел.

END – Немедленная остановка процесса перезаписи

Использование флага [END] терминирует не только текущий раунд процесса перезаписи (как это делает [L]), но также предотвращает любые последующие процессы перезаписи.

Это не относится к новым запросам, связанным с внешними перенаправлениями.

К примеру, набор правил с флагом [END]:

RewriteEngine on
RewriteRule dogs cats [END]
RewriteRule cats index.html

При открытии http://localhost/mr/dogs приведёт к ошибке «запрос /mr/cats не найден на сервере».

А эти же правила с флагом [L]:

RewriteEngine on
RewriteRule dogs cats [L]
RewriteRule cats index.html

При открытии http://localhost/mr/dogs покажут содержимое файла index.html. Это происходит по следующей схеме: при первом проходе dogs заменяется на cats и цикл обрывается из-за флага [L], но начинается новый цикл, в результате которого первое правило пропускается (нет совпадений), но срабатывает второе правило – замена cats на index.html.

Флаг [END] доступен в Apache начиная с версии 2.3.

H|handler – Отправка результирующего URI указанному Content-handler для обработки

Принуждает результирующий запрос быть обработанным указанным handler (обработчиком). Например, можно сделать так, что все файлы без расширения будут разбираться php обработчиком (сохраните эти строки в файл .htaccess):

RewriteEngine on
RewriteRule "!\." "-" [H=application/x-httpd-php]

Регулярное выражение выше !\. будет соответстовать любому запросу, в котором отсутствует буквальный символ . (точки).

Создайте файл в именем script и скопируйте туда:

<?php

echo 'PHP rules!';

Откройте в браузере адрес http://localhost/mr/script

Вместо PHP кода мы увидели результат работы скрипта.

Это также можно использовать, чтобы заставить обработчик основываться на некоторых условиях. Например, следующий фрагмент, используемый в серверном контексте, позволяет отображать файлы .php модулем mod_php, если они запрашиваются с расширением .phps:

RewriteRule "^(/source/.+\.php)s$" "$1" [H=application/x-httpd-php-source]

Регулярное выражение ^(/source/.+\.php)s$ будет соответствовать любому запросу, который начинается с /source/ за которым идёт от 1 до n символов, за которыми идёт буквальное .phps. Обратная ссылка $1 ссылается на захваченное совпадение в скобках регулярного выражения.

C|chain – Составление цепи из правил

Правило составляет цепочку со следующим правилом. Если нет совпадения с правилом, то правило(а), составляющие цепочку с ним, пропускается.

Флаг [C] или [chain] может использоваться несколько раз с идущими последовательно директивами RewriteRule, каждая из которых составляет цепочку со следующим правилом. То есть, если правило совпадает, то оно обрабатывается как обычно и управление передаётся следующему правилу. Но если правило не совпадает, тогда следующее правило, и все другие правила, которые объединены в одну цепочку, пропускаются.

Пример:

RewriteEngine on
RewriteRule !\.php - [C]
RewriteRule dogs index.html

Первое правило совпадает, если у запрашиваемого адреса нет расширения .php. Если это так, то делается проверка по следующему правилу. Если же в первом правиле совпадение отсутствует (у адреса имеется расширение .php), то второе правило пропускается.

В результате при переходе по адресу http://localhost/mr/dogs.php страница будет не найден. Но адрес http://localhost/mr/dogs покажет содержимое файла index.html.

Если убрать флаг [C]:

RewriteEngine on
RewriteRule !\.php -
RewriteRule dogs index.html

То оба адреса (http://localhost/mr/dogs.php и http://localhost/mr/dogs) покажут содержимое файла index.html.

N|next – Перезапуск процесс перезаписи начиная с первого правила

Флаг [N] приводит к тому, что набор правил начинается свою работу снова с самого начала, используя результат предыдущей работы набора правил как отправную точку. Используйте это крайне осторожно, поскольку это может привести к бесконечной петле.

Флаг [Next] можно использовать, например, если вы хотите многократно заменить определённую строку или букву в запросе. Пример показанный здесь заменит A на B везде в запросе, и продолжит это делать до тех пор, пока больше не останется A для замены.

RewriteRule "(.*)A(.*)" "$1B$2" [N]

Вы можете думать об этом как о цикле while: пока этот шаблон совпадает (т.е. пока URI ещё содержит A), выполняется подстановка (т.е. замена A на B).

В 2.4.8 и более поздних версиях, этот модуль возвращает ошибку после 32,000 повторений для защиты от ненамеренного зацикливания. Можно установить другое число повторений указав с флагом N число.

# Будет заменять по 1 символу за каждый проход цикла
RewriteRule "(.+)[><;]$" "$1" [N=64000]
# ... или остановиться после 10 повторений
RewriteRule "(.+)[><;]$" "$1" [N=10]

QSA|qsappend – Добавить строку запроса из исходного URL к строке запроса, созданной правилами перезаписи

Строкой запроса является часть запрашиваемого адреса, которая следует после символа знак вопроса (?). К примеру, в запросе /pages/123?one=two строкой запроса является выделенная жирным часть.

Когда заменяющий 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 содержит строку запроса, а целевой URI – нет, поведением RewriteRule по умолчанию является скопировать строку запроса к целевому URI. Использование флага [QSD] приводит к тому, что строка запроса будет отброшена.

Этот флаг доступен в версии 2.4.0 и более поздних.

Использование вместе [QSD] и [QSA] приведёт к тому, что [QSD] будет иметь приоритет.


Если целевой URI имеет строку запроса, то будет соблюдаться поведение по умолчанию, то есть оригинальная строка запроса будет отброшена и заменена на строку запроса в RewriteRule целевым URI.

QSL|qslast – Сделать разделителем строки самый правый знак вопроса

Интерпретировать последний (самый правый) знак вопроса в качестве разделителя строки запроса, вместо первого (самого левого) как это обычно делается. Флаг доступен в 2.4.19 и более поздних версиях.

По умолчанию, первый (самый левый) знак вопроса в подстановке отделяет путь от строки запроса. Использование флага [QSL] инструктирует RewriteRule вместо такого поведения разделять два компонента используя последний (самый правый) знак вопроса.

Это полезно при сопоставлении файлов, имеющих буквальные вопросительные знаки в их именах. Если в подстановке не используется строка запроса, к ней может быть добавлен знак вопроса в комбинации с этим флагом.

Этот флаг доступен в версии 2.4.19 и более поздних.

NE|noescape – Не экранировать специальные символы в результатах

Этот флаг не даёт mod_rewrite применять шестнадцатеричное экранирование специальных символов в результатах перезаписи.

По умолчанию, специальные символы, такие как, к примеру, & и ?, будут конвертированы в их шестнадцатеричный эквивалент. Использование флага [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 запросах.

Рассмотрим следующий пример в предварительно подготовленном окружении для тестирования (существует файл index.html). Если в .htaccess мы запишем следующее правило:

RewriteEngine on
RewriteRule index.html nothing [NS]

то запрос http://localhost/mr/ выведет содержимое индексного файла (index.html).

Если мы запишем правило без флага [NS]:

RewriteEngine on
RewriteRule index.html nothing

То это приведёт к тому, что при запросе http://localhost/mr/ сработает правило и будет выведено сообщение об ошибке, что /mr/nothing не найдено на этом сервере. Несмотря на то, что мы ни в первом ни во втором случае прямо не запрашивали файл index.html, делался подзапрос для поиска индексного файла. В первом случае индексный файл был найден, а правило замены не было выполнено, поскольку флаг [NS] запрещает его использовать в подзапросах. Во втором случае индексный файл также был найден, но из-за правила пользователю был показан файл /mr/nothing, который не существует, что вызвало ошибку 404.

S|skip – Пропустить следующее количество правил, если сработало текущее правило

Флаг [S] используется для пропуска правил, которые вы не хотите запускать. Синтаксис флага skip следующий [S=N], где N означает количество правил для пропуска (при условии совпадения RewriteRule). Это можно рассматривать как инструкцию goto в вашем наборе правил перезаписи. В следующем примере мы хотим запустить RewriteRule, только если запрошенный URI не является файлом или каталогом.

# Запрашивается ли несуществующий файл?
RewriteCond "%{REQUEST_FILENAME}" "!-f"
RewriteCond "%{REQUEST_FILENAME}" "!-d"
# Если так, то пропустить следующие RewriteRules
RewriteRule ".?" "-" [S=2]

RewriteRule "(.*\.gif)" "images.php?$1"
RewriteRule "(.*\.html)" "docs.php?$1"

Эта техника полезна, поскольку RewriteCond применяются только к RewriteRule, следующей немедленно после них. Если вы хотите сделать RewriteCond применимой к нескольким RewriteRules, одна из возможных техник – это отрицание этих условий и добавление RewriteRule с флагом [Skip]. Вы можете использовать это для создания псевдо-конструкций if-then-else: последнее правило условия then становится skip=N, где N это количество правил в else-условии:

# Существует ли файл?
RewriteCond "%{REQUEST_FILENAME}" "!-f"
RewriteCond "%{REQUEST_FILENAME}" "!-d"
# Создаём конструкцию if-then-else пропуская 3 строки если мы хотим перейти на строфу «ещё».
RewriteRule ".?" "-" [S=3]

# ЕСЛИ файл существует, тогда:
    RewriteRule "(.*\.gif)" "images.php?$1"
    RewriteRule "(.*\.html)" "docs.php?$1"
    # Пропускаем мимо строфу «ещё».
    RewriteRule ".?" "-" [S=1]
# ЕЩЁ...
    RewriteRule "(.*)" "404.php?file=$1"
# КОНЕЦ

Вероятно, удобнее достичь конфигураций такого рода используя вместо этого директивы <If>, <ElseIf> и <Else>.

T|type – Принудительная установка MIME-типа целевого файла на указанный тип

Устанавливает MIME тип с которым будет отправлен результирующий ответ. Это имеет такой же эффект как директива AddType.

Например, вы можете использовать следующую технику для обработки исходного кода Perl в качестве простого текста, если запрос сделан особым образом:

# Обработать .pl файлы как простой текст
RewriteRule "\.pl$" "-" [T=text/plain]

Или, допустим, у вас есть камера, которая создаёт изображения jpeg без файлового расширения, вы можете принудительно обрабатывать эти изображения с правильным типом MIME на основе их имени файла:

# Файлы с 'IMG' в имени являются jpg изображениями.
RewriteRule "IMG" "-" [T=image/jpg]

Обратите внимание, что это тривиальный пример и эту реализацию лучше было бы сделать с использованием <FilesMatch>. Всегда рассматривайте альтернативные решения проблемы, прежде чем прибегать к модулю rewrite, который будет всегда менее эффективным решением, чем альтернативы.

Если используете в контексте директорий, используйте - (чёрточку) в качестве подстановки для всего раунда обработки mod_rewrite, иначе MIME-тип, установленный с этим флагом, будет потерян из-за внутренней повторной обработки (включая последующие раунды обработки mod_rewrite). Флаг L может быть полезен в этом контексте для завершения текущего раунда обработки mod_rewrite.

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 (не экранировать пробелы на +) – Если обратные ссылки будут экранированы, пробелы должны быть экранированы в %20 вместо +

Флаг [BNP] инструктирует RewriteRule экранировать символ пробела в обратной ссылке как %20, а не '+'. Полезно, когда обратная ссылка будет использоваться в компоненте пути, а не строке запроса.

Этот флаг доступен в версии 2.4.26 и более поздних.

CO|cookie – Устанавливает куки в клиентский браузер

Флаг [CO] или [cookie] позволяет вам устанавливать куки, когда совпадает конкретное RewriteRule. Аргумент состоит из трёх обязательных элементов и четырёх опциональных полей.

Полный синтаксис для этого флага, включая все атрибуты, следующий:

[CO=ИМЯ:ЗНАЧЕНИЕ:ДОМЕН:время жизни:путь:secure:httponly]

Если нужен буквальный символ ':' в любом поле куки, доступен альтернативный синтаксис. Чтобы перейти к альтернативному синтаксису, «ИМЯ» кукиз должно начинаться с символа ';' и разделителем полей должен быть ';'.

[CO=;ИМЯ;ЗНАЧЕНИЕ:ЕЩЁ ЗНАЧЕНИЕ;ДОМЕН;время жизни;путь;secure;httponly]

Для установки куки вы должны объявить имя, значение и домен.

Домен

Домен для которого вы хотите чтобы куки была валидна. Это может быть имя хоста, такое как www.example.com, или это может быть домен, такой как .example.com. Должно быть по крайней мере две части, разделённых точкой. То есть это не может быть просто .com или .net. Кукиз такого рода запрещены моделью безопасности кукиз.

Опционально вы можете установить следующие значения:

Время жизни

Время, в течение которого куки будет сохраняться, в минутах.

Значение 0 говорит, что куки будет храниться только для текущей сессии браузера. Это значение по умолчанию, если ничего не указано.

Путь

Путь на текущем веб-сайте, для которого куки является валидной, такой как /customers/ или /files/download/.

По умолчанию он установлен на / - то есть, это весь веб-сайт.

Безопасность

Если установлена на secure, true или 1, куки будет разрешено передаваться только через безопасные (https) соединения.

httponly

Если установлено на HttpOnly, true или 1, куки будут иметь установленный флаг HttpOnly, который означает, что куки недоступны для кода JavaScript в браузерах, которые поддерживают эту функцию.

Рассмотрим пример:

RewriteEngine On
RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.com:1440:/]

В данном примере правило не перезаписывает запрос. Указанная чёрточка "-" в качестве цели перезаписи говорит mod_rewrite оставить запрос неизменным. Вместо этого, оно устанавливает куки с именем 'frontdoor' на значение 'yes'. Куки валидно для любого хоста на домене .example.com. Срок действительности для него установлен на 1440 минут (24 часов) и возвращается для всех URI.

DPI|discardpath – Приводит к отбрасыванию части PATH_INFO переписанного URI

Флаг DPI приводит к тому, что часть PATH_INFO переписанного URI отбрасывается.

Этот флаг доступен в версии 2.2.12 и более поздних.

В контексте директорий, URI, который сравнивает каждый 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=ПЕРЕМЕННАЯ:ЗНАЧЕНИЕ]
[E=!ПЕРЕМЕННАЯ]

ЗНАЧЕНИЕ может содержать обратные ссылки ($N или %N), которые раскрываются.

Используя короткую форму

[E=ПЕРЕМЕННАЯ]

вы можете установить пустое значение переменной окружения с именем ПЕРЕМЕННАЯ.

Форма

[E=!ПЕРЕМЕННАЯ]

позволяет снять настройку ранее установленной переменной окружения с именем ПЕРЕМЕННАЯ.

Переменные окружения могут использоваться в различных контекстах, включая CGI программы, другие директивы RewriteRule или директивы CustomLog.

Следующий пример устанавливает переменную окружения с именем 'image' на значение '1' если запрошенный URI является файлом изображения. Затем эта переменная окружения используются для исключения этих запросов из журнала доступа.

RewriteRule "\.(png|gif|jpg)$" "-" [E=image:1]
CustomLog "logs/access_log" combined env=!image

Помните, что этот же самый эффект можно получить используя SetEnvIf. Эта техника предложена как пример, а не как рекомендация.

G|gone – Возвращает клиентскому браузеру ответ 410 GONE

Флаг [G] заставляет сервер возвращать с ответом статус 410 Gone. Это говорит о том, что ресурс был ранее доступен, но больше его нет.

Как с флагом [F], вы обычно будете использовать для перезаписи цели синтаксис "-", когда используется флаг [G]:

RewriteRule "oldproduct" "-" [G,NC]

Когда используется [G], то [L] подразумевается – т.е. ответ возвращается немедленно, и другие правила не оцениваются.

P|proxy – Заставляет URL-адрес подстановки быть внутренне отправленным в качестве прокси-запроса

Использование флага [P] приводит к тому, что запрос обрабатывается в mod_proxy и передаётся через прокси запрос. Например, если вы хотите, чтобы все запросы изображений обрабатывались сторонним сервером картинок, вы можете сделать что-то вроде следующего:

RewriteRule "/(.*)\.(jpg|gif|png)$" "http://images.example.com/$1.$2" [P]

Использование флага [P] подразумевает [L] – то есть запрос немедленно передаётся через прокси и любые другие правила не рассматриваются.

Вы должны убедиться, что строка подстановки является валидным URI (обычно начинается с http://имя_хоста), который может быть обработан в mod_proxy. Если это не так, вы получите ошибку от прокси модуля. Используйте этот флаг для достижения более эффективной реализации директивы ProxyPass, чтобы отображать удаленный контент в пространство имен локального сервера.

Предупреждение о безопасности

Будьте осторожны при построении целевого URL правила, учитывайте влияние на безопасность, позволяя клиенту влиять на набор URL-адресов, к которым ваш сервер будет обращаться как прокси-сервер. Убедитесь, что схема и имя узла URL-адреса являются либо фиксированными, либо не позволяют клиенту чрезмерно влиять на них.

Предупреждение о производительности

Использование этого флага запускает использование mod_proxy без обработки постоянных подключений. Это означает, что производительность вашего прокси-сервера будет лучше, если вы настроите его с помощью ProxyPass или ProxyPassMatch. Это связано с тем, что этот флаг запускает использование дефолтного воркера, который не обрабатывает пул соединений/повторное использование. Избегайте использования этого флага и предпочитайте те директивы, когда можете.

Примечание: mod_proxy должен быть включен, чтобы использовать этот флаг.

PT|passthrough – Заставляет результирующий URI быть переданным обратно в механизм сопоставления URL-адресов для обработки другими URI-на-имя_файла трансляторами, таких как Alias или Redirect

Предполагается, что цель (или строка подстановки) в RewriteRule является по умолчанию файловым путем. Использование флага [PT] принудительно приводит к тому, что она вместо этого начинает рассматриваться как URI. Другими словами, использование флага [PT] приводит к возврату результата RewriteRule обратно к сопоставлению URL-адресов, таким образом основанные на location сопоставления, такие как, к примеру, 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. Единственный способ обойти это, переписать на -.

Продолжение: «Полное руководство по mod_rewrite (часть 4): Директива RewriteCond».


Рекомендуется Вам:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *