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


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

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

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

3. Флаги RewriteRule

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

4.1 Функции и синтаксис RewriteCond

4.2 Строка тестирования RewriteCond

4.3 ​Шаблон условия RewriteCond

4.4 Флаги RewriteCond

4.5 Пример

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

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

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

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


Функции и синтаксис RewriteCond

Директива RewriteCond определяет условие, при котором будет иметь место перезапись. То есть мы ставим в зависимость выполнения правила не только от условия совпадения с Шаблоном, но и от других условий, которые могут не относиться к содержимому строки запроса. Например, правило может срабатывать (или наоборот, не срабатывать) если запрашиваемый адрес указывает на реально существующий в файловой системе файл, правило может быть отключено для определённых клиентских браузеров, либо в определённое время суток. Всё это можно сделать с помощью RewriteCond.

Синтаксис использования:

RewriteCond СтрокаТестирования ШаблонУсловия [флаги]

RewriteCond определяет условие применения правила. Одна или более директив RewriteCond могут предшествовать директиве RewriteRule. Последующее правило будет использоваться только в том случае, если текущее состояние URI соответствует его Шаблону, И если выполняются условия RewriteCond.

Строка тестирования RewriteCond

СтрокаТестирования – это строка, которая может содержать следующие расширенные конструкции в дополнение к простому тексту:

  • Обратные ссылки RewriteRule: это обратные ссылки вида $N (0 <= N <= 9). С $1 по $9 обеспечивают доступ к сгруппированным частям (помещённым в скобки) Шаблона из RewriteRule, который является субъектом текущего набора условий RewriteCond. $0 предоставляет доступ к целой строке, совпавшей с этим Шаблоном.
  • Обратные ссылки RewriteCond: это обратные ссылки вида %N (0 <= N <= 9). С %1 по %9 предоставляют доступ к сгруппированным частям (снова в кавычках) Шаблона из последнего совпавшего RewriteCond в текущем наборе условий. %0 предоставляет доступ к целой строке, совпавшей с этим Шаблоном.
  • Расширения RewriteMap: это расширения в форме ${mapname:key|default}. Смотрите документацию по RewriteMap для дополнительной информации.
  • Серверные переменные: это переменные вида %{ NAME_OF_VARIABLE } где NAME_OF_VARIABLE может быть строкой, взятой из следующего списка:
Переменные Описание
HTTP заголовки
HTTP_ACCEPT Запрашивает типы контента, выраженные в виде типов MIME, которые клиент может понять. Используя согласование контента, сервер затем выбирает одно из предложений, использует его и информирует клиента о своём выборе заголовком ответа Content-Type. Браузеры устанавливают соответствующие значения для этого заголовка в зависимости от контекста, в котором выполняется запрос: при обработке таблицы стилей CSS для запроса задается другое значение, чем при выборе изображения, видео или сценария.
HTTP_COOKIE Содержит сохраненные HTTP-файлы cookie, ранее отправленные сервером с заголовком Set-Cookie.
HTTP_FORWARDED Содержит информацию с клиентской стороны, которая изменена или потеряна когда в путь запроса вовлечён прокси.
HTTP_HOST Указывает доменное имя сервера (для виртуального хостинга) и (необязательно) номер порта TCP, который прослушивает сервер.
HTTP_PROXY_CONNECTION Определяет, остается ли сетевое соединение открытым после завершения текущей транзакции. Если отправляется keep-alive, соединение является постоянным и не закрытым, что позволяет выполнять последующие запросы на один и тот же сервер.
HTTP_REFERER Содержит адрес предыдущей веб-страницы, с которой была сделана ссылка на запрашиваемую страницу.
HTTP_USER_AGENT Содержит строку-характеристику, которая позволяет сетевым протоколам идентифицировать тип приложения, операционную систему, поставщика программного обеспечения или версию программного обеспечения запрашивающего программного агента.
Внутренние сервера
DOCUMENT_ROOT DocumentRoot текущего vhost.
SCRIPT_GROUP Имя группы скрипта.
SCRIPT_USER Имя пользователя владельца скрипта.
SERVER_ADDR IP-адрес виртуального хоста, обслуживающего запрос.
SERVER_ADMIN ServerAdmin текущего vhost
SERVER_NAME ServerName (включает схему, доменное имя или IP адрес и порт) текущего vhost.
SERVER_PORT Порт сервера текущего vhost, также смотрите ServerName.
SERVER_PROTOCOL Протокол, используемый запросом.
SERVER_SOFTWARE Строка с версией сервера.
Подключение и запросы
AUTH_TYPE Настроенный AuthType (варианты: None|Basic|Digest|Form)
CONN_REMOTE_ADDR С 2.4.8: IP адрес пира соединения (смотрите модуль mod_remoteip).
CONTEXT_PREFIX Префикс URI, который соответствует каталогу CONTEXT_DOCUMENT_ROOT, без конечной косой черты
CONTEXT_DOCUMENT_ROOT Корневой каталог контекста на диске для текущего ресурса, без конечного слэша
IPV6 "on" если подключение использует IPv6, в противном случае "off"
PATH_INFO Завершающая информация имени пути, которая следует после реального расположения файла или несуществующий файл в существующем каталоге независимо от того, является ли запрос принятым или отклонённым, смотрите AcceptPathInfo. Например, допустим расположение /test/ указывает на директорию, которая содержит только один файл here.html. Тогда запрос /test/here.html/more и /test/nothere.html/more оба соберут /more в качестве значения PATH_INFO.
QUERY_STRING Строка запроса (следует после символа ? (знак вопроса)) текущего запроса к серверу.
REMOTE_ADDR IP адрес удалённого хоста.
REMOTE_HOST Имя хоста удалённого хоста.
REMOTE_IDENT Имя пользователя, утсановленное mod_ident.
REMOTE_PORT Порт удалённого хоста (2.4.26 и более поздние)
REMOTE_USER Имя аутентифицированного пользователя, если есть.
REQUEST_METHOD HTTP метод входящего запроса (например, GET, POST, HEAD).
SCRIPT_FILENAME То же самое, что и REQUEST_FILENAME.
Дата и время
TIME_YEAR Текущий год (например, (2018)
TIME_MON Текущий месяц (01, …, 12)
TIME_DAY Текущий день месяца (01, …)
TIME_HOUR Часы текущего времени (00, …, 23)
TIME_MIN Минуты текущего времени
TIME_SEC Секунды текущего времени
TIME_WDAY День недели (начинается с 0 для Воскресенья)
TIME Дата и время в формате 20180924214559
Специальные
API_VERSION Версия Apache httpd module API (внутреннего интерфейса между сервером и модулем) в текущей сборке httpd, как определена в include/ap_mmn.h. Версия модуля API соответствует версии используемого Apache httpd. Обычно это интересно только для авторов модулей.
CONN_REMOTE_ADDR С 2.4.8: IP адрес пира соединения (смотрите модуль mod_remoteip).
HTTPS Будет содержать текст "on" если соединение использует SSL/TLS, в противном случае - "off". (Эта переменная может безопасно использоваться независимо от того, загружен модуль mod_ssl или нет).
IS_SUBREQ Будет содержать текст "true" если обрабатываемый в данный момент запрос является подзапросом, в противном случае "false". Подзапросы могут генерироваться модулями, которым нужно преобразовать дополнительные файлы или URI чтобы завершить их задачи.
REMOTE_ADDR IP удалённого хоста (смотрите модуль mod_remoteip).
REQUEST_FILENAME Полный путь в локальной файловой системе до файла или скрипта, совпадающего с запросом, если он уже был определён сервером во время упоминания REQUEST_FILENAME. В зависимости от значения AcceptPathInfo, сервер может использовать только некоторые предшествующие компоненты REQUEST_URI для сопоставления запроса с файлом.
REQUEST_SCHEME Будет содержать схему запроса (обычно "http" или "https"). На это значение может влиять ServerName.
REQUEST_URI Компонент пути запрошенного URI, такой как "/index.html". Здесь исключена строка запроса, которая доступна в своей собственной переменной под именем QUERY_STRING.
THE_REQUEST Полная строка запроса HTTP отправленная браузером к серверу (например, "GET /index.html HTTP/1.1"). Она не включает любые дополнительные заголовки, отправленные браузером. Это значение не экранировано (кодировано), в отличии от большинства других переменных.

Эти переменные все соответствуют названным подобным образом HTTP MIME-заголовкам, переменным C для Apache HTTP сервера или полям struct tm системы Unix.

SERVER_NAME и SERVER_PORT зависят от значений UseCanonicalName и UseCanonicalPhysicalPort соответственно.

Если СтрокаТестирования имеет специальное значение expr, ШаблонУсловия будет обрабатываться как ap_expr. HTTP заголовки, на которые указано в выражении, будут добавлены к заголовку Vary, если не дан флаг novary.


Другие вещи, о которых вы должны знать:

  1. Переменные SCRIPT_FILENAME и REQUEST_FILENAME содержат одинаковое значение – значение поля filename внутренней структуры request_rec сервера Apache HTTP. Первое имя – это имя хорошо известной CGI переменной, а второе – соответствующий двойник REQUEST_URI (которые содержит значение поля uri из of request_rec).

Если случилась подстановка и перезапись продолжается, значение обеих переменных соответственно будет обновлено.

Если используется контекст сервера (то есть до того, как запрос сопоставляется с файловой системой), SCRIPT_FILENAME и REQUEST_FILENAME не могут содержать полный путь к локальной файловой системе, поскольку на этом этапе обработки путь неизвестен. В этом случае изначально обе переменные будут содержать значение REQUEST_URI. Чтобы получить полный путь в локальной файловой системе запроса в контексте сервера, используйте основанный на URL look-ahead %{LA-U:REQUEST_FILENAME}, для определения конечного значение REQUEST_FILENAME.


  1. %{ENV:переменная}, где переменная может быть переменной окружения, также доступно. Она ищется через внутреннюю структуру Apache httpd и (если там не найдена) через getenv() из процесса Apache httpd.
  2. %{SSL:переменная}, где переменная – это имя переменной окружения SSL, может использоваться в независимости от того, загружен ли mod_ssl, но всегда будет раскрываться в пустую строку, если не загружен. Пример: %{SSL:SSL_CIPHER_USEKEYSIZE} может раскрыться в 128. Эти переменные доступны даже без настройки опции StdEnvVars директивы SSLOptions.
  3. %{HTTP:заголовок}, где заголовок может быть именем HTTP MIME-заголовка, может всегда использоваться для получения значения заголовка, отправленного в HTTP запросе. Пример: %{HTTP:Proxy-Connection} – это значение HTTP заголовка «Proxy-Connection:».

Если HTTP заголовок используется в условии, этот заголовок добавляется к заголовку Vary ответа в случае, если для данного запроса условие вычисляется как истина. Он не добавляется если условие вычисляется для заголовка как лож. Добавление HTTP заголовка к заголовку Vary ответа необходимо для правильного кэширования.

Следует иметь в виду, что условия соответствуют логике короткого контура в случае флага 'ornext|OR', так что некоторые условия могут вообще не оцениваться.

  1. %{LA-U:переменная}может использоваться для look-aheads, которые выполняют внутренний запрос (основанный на URL) для определения конечного значения переменной. Это можно использовать для доступа к переменной для перезаписи, которая недоступна на текущем этапе, но будет установлена на более поздней стадии.

Например, чтобы переписать в соответствии с переменной REMOTE_USER из контекста сервера (файл httpd.conf), вы должны использовать %{LA-U:REMOTE_USER} - эта переменная задается фазами авторизации, которые появляются после преобразования URL (во время которой работает mod_rewrite).

С другой стороны, поскольку mod_rewrite реализует контекст для каталога (файл .htaccess) через фазу Fixup API и, поскольку фазы авторизации приходят до этого этапа, вы можете использовать %{REMOTE_USER} в этом контексте.

  1. %{LA-F:переменная} может использоваться для выполнения внутреннего подзапроса (на основе имени файла) для определения конечного значения переменной. В большинстве случаев это то же самое, что и LA-U выше.

Шаблон условия RewriteCond

ШаблонУсловия – это шаблон условия, регулярное выражение, которое применяется к текущему экземпляру СтрокаТестирования. СтрокаТестирования сначала оценивается перед сопоставлением с ШаблономУсловия.

ШаблонУсловия обычно является регулярным выражением, совместимым с perl, но имеется дополнительный синтаксис для выполнения других полезных тестов в отношении СтрокиТестирования:

  1. Вы можете добавить перед строкой шаблона символ '!' (восклицательный знак) для отрицания результата условия, независимо от того, какой тип ШаблонаУсловия используется.

Пример правила блокировки всех пользователей с пустым Referer, кроме одного IP адреса (127.0.0.1):

RewriteEngine   on
RewriteCond "%{REMOTE_ADDR}"	"!127.0.0.1"
RewriteCond %{HTTP_REFERER}	^$
RewriteRule ^.* -	[F,L]
  1. Вы можете выполнять лексикографическое сравнение строк (сводится к тому, какая бы строка шла первой в случае их расстановки в алфавитном порядке):

<CondPattern

Лексикографически предшествует

Обрабатывает ШаблонУсловия как обычную строку и сравнивает ее лексикографически со СтрокойТестирования. Истина, если СтрокаТестирования лексикографически предшествует ШаблонуУсловия.

>CondPattern

Лексикографически следует


Обрабатывает ШаблонУсловия как обычную строку и сравнивает ее лексикографически со СтрокойТестирования. Истинно, если СтрокаТестирования лексикографически следует ШаблонуУсловия.

=CondPattern

Лексикографически равный

Обрабатывает ШаблонУсловия как обычную строку и сравнивает ее лексикографически со СтрокойТестирования. Истина, если СтрокаТестирования лексикографически равна ШаблонуУсловия (две строки в точности равны, символ в символ). Если ШаблонУсловия является "" (двумя кавычками), это сравнивает СтрокуТестирования с пустой строкой.

<=CondPattern

Лексикографически меньше или равно

Обрабатывает ШаблонУсловия как обычную строку и сравнивает ее лексикографически со СтрокойТестирования. Истина, если СтрокаТестирования лексикографически предшествует ШаблонуУсловия или равна ШаблонуУсловия (две строки равны, символ в символ).

>=CondPattern

Лексикографически больше или равно

Обрабатывает ШаблонУсловия как обычную строку и сравнивает ее лексикографически со СтрокойТестирования. Истина, если со СтрокаТестирования лексикографически следует за ШаблономУсловия или равна ШаблонуУсловия (две строки равны, символ в символ).

  1. Вы можете выполнять целочисленные сравнения:

-eq

Численно равна

СтрокаТестирования обрабатывается как целое число и численно сравнивается со СтрокойТестирования. Истина, если они численно равны.

-ge

Численно больше или равно


СтрокаТестирования обрабатывается как целое число и численно сравнивается с ШаблономУсловия. Истинно, если СтрокаТестирования численно больше или равно ШаблонаУсловия.

-gt

Численно больше, чем

СтрокаТестирования обрабатывается как целое число и численно сравнивается с ШаблономУсловия. Истинно, если СтрокаТестирования численно больше, чем ШаблонУсловия.

-le

Численно меньше или равно

СтрокаТестирования обрабатывается как целое число и численно сравнивается с ШаблономУсловия. Истинно, если СтрокаТестирования численно меньше или равно ШаблонуУсловия. Избегайте путаницы с -l, при использовании вариант -L или -h.

-lt

Численно меньше

СтрокаТестирования обрабатывается как целое число и численно сравнивается с ШаблономУсловия. Истинно, если СтрокаТестирования численно меньше ШаблонаУсловия. Избегайте путаницы с -l, используя вариант -L или -h.

-ne

Численно не равна

СтрокаТестирования обрабатывается как целое число и численно сравнивается с ШаблономУсловия. Истинно, если они отличаются друг от друга. Это эквивалентно !-eq.

  1. Вы можете выполнять различные тесты атрибутов файлов:

-d

Является ли это каталогом

Обрабатывает СтрокуТестирования как путь и проверяет, существует ли она или нет, и является ли каталогом.

-f

Является ли это обычным файлом

Обрабатывает СтрокуТестирования как путь и проверяет, существует ли она или нет, и является ли обычным файлом.

-F

Существующий файл, через подзапрос.

Проверяет, является ли СтрокаТестирования допустимым файлом, доступным через все настроенные в данный момент элементы управления доступом для этого пути. Для выполнения проверки используется внутренний подзапрос, поэтому используйте его с осторожностью – это может повлиять на производительность вашего сервера!

-h

Является ли это символической ссылкой, псевдоним для -l.

См. -l.

-l

Является ли это символической ссылкой.

Обрабатывает СтрокуТестирования как путь и проверяет, существует ли она или нет, и является ли символической ссылкой. Можно также использовать -L или -h, если есть вероятность путаницы, например, при использовании тестов -lt или -le.

-L

Является ли символической ссылкой, псевдоним для -l.

См. -l.

-s

Является ли обычным файлом с размером.

Обрабатывает СтрокуТестирования как путь и проверяет, существует ли она или нет, и является ли обычным файлом с размером больше нуля.

-U

Является ли существующим URL-адресом через подзапрос.

Проверяет, является ли СтрокаТестирования допустимым URL-адресом, доступным через все настроенные в данный момент элементы управления доступом для этого пути. Для выполнения проверки используется внутренний подзапрос, поэтому используйте это с осторожностью – это может повлиять на производительность вашего сервера!

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

-x

Имеет ли разрешения на выполнение.

Обрабатывает СтрокуТестирования как путь и проверяет, существует ли она или нет, и имеет ли разрешения на выполнение. Эти разрешения определяются в соответствии с ОС на которой работает сервер.

Например:

RewriteCond /var/www/%{REQUEST_URI} !-f
RewriteRule ^(.+) /other/archive/$1 [R]
  1. Если СтрокаТестирования имеет специальное значение expr, ШаблонУсловия будет рассматриваться как ap_expr.

В приведенном ниже примере -strmatch используется для сравнения REFERER с именем хоста сайта для блокирования нежелательноого хотлинкинга.

RewriteCond expr "! %{HTTP_REFERER} -strmatch '*://%{HTTP_HOST}/*'"
RewriteRule "^/images" "-" [F]

Флаги RewriteCond

Вы также можете установить специальные флаги для CondPattern, добавив [флаги] в качестве третьего аргумента в директиву RewriteCond, где flags – список, разделенный запятыми, из любого из следующих флагов:

  • 'nocase|NC' (без учёта регистра)

Это делает тест нечувствительным к регистру – различия между «A-Z» и «a-z» игнорируются как в расширенной СтрокеТестирования , так и в ШаблонеУсловия. Этот флаг эффективен только для сравнения между СтрокойТестирования и ШаблономУсловия. Он не влияет на проверки файловой системы и подзапросов.

  • 'ornext|OR' (или следующее условие)

Используйте это, чтобы комбинировать условия правила связкой ИЛИ вместо И, которая подразумевается по умолчанию. Типичный пример:

RewriteCond "%{REMOTE_HOST}"  "^host1"  [OR]
RewriteCond "%{REMOTE_HOST}"  "^host2"  [OR]
RewriteCond "%{REMOTE_HOST}"  "^host3"
RewriteRule ...какие-то специальные правила для любого из этих хостов... Без этого флага, вам бы пришлось писать три раза пару условие/правило.
  • 'novary|NV' (без vary)

Если в условии используется HTTP-заголовок, этот флаг предотвращает добавление этого заголовка в заголовок ответа Vary.

Использование этого флага может нарушить правильное кэширование ответа, если представление этого ответа зависит от значения этого заголовка. Поэтому этот флаг должен использоваться только в том случае, если смысл заголовка Vary хорошо понят.

Пример:

Чтобы показать главную страницу сайта в соответствии с заголовком запроса «User-Agent:», вы можете использовать следующее:

RewriteCond  "%{HTTP_USER_AGENT}"  "(iPhone|Blackberry|Android)"
RewriteRule  "^/$"                 "/homepage.mobile.html"  [L]

RewriteRule  "^/$"                 "/homepage.std.html"     [L]

Объяснение: Если вы используете браузер, который идентифицирует себя как мобильный браузер (обратите внимание, что пример неполный, так как есть много других мобильных платформ), показывается мобильная версия домашней страницы. В противном случае будет использоваться стандартная страница.

Продолжение: «Полное руководство по mod_rewrite (часть 5): Частые случаи и примеры использования mod_rewrite».


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

2 комментария to Полное руководство по mod_rewrite (часть 4): Директива RewriteCond

  1. Аноним:

    может не срабатывать (или наоборот, не срабатывать)

Добавить комментарий для Alexey Отменить ответ

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