Выражения в Apache HTTP Server
Исторически существует несколько вариантов синтаксиса выражений, используемых для задания условий в различных модулях Apache HTTP Server. В настоящее время ведётся работа над тем, чтобы использовать во всех директивах конфигурации только один вариант, называемый ap_expr. В этом документе описан анализатор выражений ap_expr.
Выражение ap_expr предназначено для замены большинства других вариантов выражений в HTTPD. Например, устаревшие выражения SSLRequire можно заменить на Require expr.
Грамматика в нотации Бэкуса — Наура
Форма Бэкуса — Наура (BNF) — это способ записи контекстно-свободных грамматик, часто используемый для описания синтаксиса языков программирования. В большинстве случаев выражения используются для задания логических значений. В этом случае начальным символом в BNF является expr. Однако некоторые директивы, например LogMessage, принимают выражения, результатом которых является строковое значение. Для них начальным символом в BNF является string.
expr ::= "true" | "false"
| "!" expr
| expr "&&" expr
| expr "||" expr
| "(" expr ")"
| comp
comp ::= stringcomp
| integercomp
| unaryop word
| word binaryop word
| word "in" "{" wordlist "}"
| word "in" listfunction
| word "=~" regex
| word "!~" regex
stringcomp ::= word "==" word
| word "!=" word
| word "<" word
| word "<=" word
| word ">" word
| word ">=" word
integercomp ::= word "-eq" word | word "eq" word
| word "-ne" word | word "ne" word
| word "-lt" word | word "lt" word
| word "-le" word | word "le" word
| word "-gt" word | word "gt" word
| word "-ge" word | word "ge" word
wordlist ::= word
| wordlist "," word
word ::= word "." word
| digit
| "'" string "'"
| """ string """
| variable
| rebackref
| function
string ::= stringpart
| string stringpart
stringpart ::= cstring
| variable
| rebackref
cstring ::= ...
digit ::= [0-9]+
variable ::= "%{" varname "}"
| "%{" funcname ":" funcargs "}"
rebackref ::= "$" [0-9]
function ::= funcname "(" word ")"
listfunction ::= listfuncname "(" word ")" Переменные
Анализатор выражений предоставляет ряд переменных вида %{HTTP_HOST}. Обратите внимание, что значение переменной может зависеть от этапа обработки запроса, на котором она вычисляется. Например, выражение, используемое в директиве <If >, вычисляется до выполнения аутентификации. Поэтому в этом случае значение %{REMOTE_USER} не будет задано.
Следующие переменные предоставляют значения указанных заголовков HTTP-запроса. Значения других заголовков можно получить с помощью функции req. Использование этих переменных может привести к добавлению имени заголовка в заголовок Vary ответа HTTP, за исключением случаев, отдельно отмеченных для директивы, принимающей выражение. Чтобы избежать такого поведения, можно использовать функцию req_novary.
| Имя |
|---|
HTTP_ACCEPT |
HTTP_COOKIE |
HTTP_FORWARDED |
HTTP_HOST |
HTTP_PROXY_CONNECTION |
HTTP_REFERER |
HTTP_USER_AGENT |
Другие переменные, связанные с запросом
| Имя | Описание |
|---|---|
REQUEST_METHOD | Метод входящего запроса HTTP (например, GET) |
REQUEST_SCHEME | Схема URI запроса |
REQUEST_URI | Путь URI запроса |
DOCUMENT_URI | То же, что и REQUEST_URI
|
REQUEST_FILENAME | Полный путь в локальной файловой системе к файлу или скрипту, соответствующему запросу, если сервер уже определил его к моменту обращения к REQUEST_FILENAME. В противном случае, например при использовании в контексте виртуального хоста, значение совпадает с REQUEST_URI |
SCRIPT_FILENAME | То же, что и REQUEST_FILENAME
|
LAST_MODIFIED | Дата и время последнего изменения файла в формате 20101231235959, если сервер уже определил их к моменту обращения к LAST_MODIFIED. |
SCRIPT_USER | Имя пользователя — владельца скрипта. |
SCRIPT_GROUP | Имя группы, к которой относится скрипт. |
PATH_INFO | Хвостовая часть пути; см. AcceptPathInfo
|
QUERY_STRING | Строка запроса текущего запроса |
IS_SUBREQ | "true", если текущий запрос является подзапросом, и "false" в противном случае |
THE_REQUEST | Полная строка запроса (например, "GET /index.html HTTP/1.1") |
REMOTE_ADDR | IP-адрес удалённого хоста |
REMOTE_PORT | Порт удалённого хоста (версия 2.4.26 и новее) |
REMOTE_HOST | Имя удалённого хоста |
REMOTE_USER | Имя аутентифицированного пользователя, если он есть (недоступно во время <If>) |
REMOTE_IDENT | Имя пользователя, заданное директивой mod_ident
|
SERVER_NAME | ServerName текущего виртуального хоста |
SERVER_PORT | Порт сервера текущего виртуального хоста; см. ServerName
|
SERVER_ADMIN | ServerAdmin текущего виртуального хоста |
SERVER_PROTOCOL | Протокол, используемый запросом |
DOCUMENT_ROOT | DocumentRoot текущего виртуального хоста |
AUTH_TYPE | Настроенный AuthType (например, "basic") |
CONTENT_TYPE | Тип содержимого ответа (недоступно во время <If>) |
HANDLER | Имя обработчика, создающего ответ |
HTTP2 | "on", если запрос использует http/2, и "off" в противном случае |
HTTPS | "on", если запрос использует https, и "off" в противном случае |
IPV6 | "on", если соединение использует IPv6, и "off" в противном случае |
REQUEST_STATUS | Код ошибки HTTP для запроса (недоступно во время <If>) |
REQUEST_LOG_ID | Идентификатор ошибки запроса в журнале ошибок (см. ErrorLogFormat) |
CONN_LOG_ID | Идентификатор ошибки соединения в журнале ошибок (см. ErrorLogFormat) |
CONN_REMOTE_ADDR | IP-адрес узла-партнёра соединения (см. модуль mod_remoteip) |
CONTEXT_PREFIX | |
CONTEXT_DOCUMENT_ROOT |
Прочие переменные
| Имя | Описание |
|---|---|
TIME_YEAR | Текущий год (например, 2010) |
TIME_MON | Текущий месяц (01, ..., 12) |
TIME_DAY | Текущий день месяца (01, ...) |
TIME_HOUR | Часовая часть текущего времени (00, ..., 23) |
TIME_MIN | Минутная часть текущего времени |
TIME_SEC | Секундная часть текущего времени |
TIME_WDAY | День недели (нумерация начинается с 0 для воскресенья) |
TIME | Дата и время в формате 20101231235959
|
SERVER_SOFTWARE | Строка версии сервера |
API_VERSION | Дата версии API (магическое число модуля) |
Некоторые модули регистрируют дополнительные переменные; см., например, mod_ssl.
Бинарные операторы
За исключением некоторых встроенных операторов сравнения, бинарные операторы имеют вид "-[a-zA-Z][a-zA-Z0-9_]+", то есть состоят из дефиса и как минимум двух символов. Регистр букв в имени не учитывается. Модули могут регистрировать дополнительные бинарные операторы.
Операторы сравнения
| Имя | Альтернатива | Описание |
|---|---|---|
== | = | Равенство строк |
!= | Неравенство строк | |
< | Строка меньше | |
<= | Строка меньше или равна | |
> | Строка больше | |
>= | Строка больше или равна | |
=~ | Строка соответствует регулярному выражению | |
!~ | Строка не соответствует регулярному выражению | |
-eq | eq | Равенство целых чисел |
-ne | ne | Неравенство целых чисел |
-lt | lt | Меньше (целые числа) |
-le | le | Меньше или равно (целые числа) |
-gt | gt | Больше (целые числа) |
-ge | ge | Больше или равно (целые числа) |
Другие бинарные операторы
| Имя | Описание |
|---|---|
-ipmatch | IP-адрес соответствует адресу/маске подсети |
-strmatch | левая строка соответствует шаблону, заданному правой строкой (содержащей подстановочные символы *, ?, []) |
-strcmatch | то же, что и -strmatch, но без учёта регистра |
-fnmatch | то же, что и -strmatch, но подстановочные символы не соответствуют косым чертам |
Унарные операторы
Унарные операторы принимают один аргумент и имеют вид "-[a-zA-Z]", то есть состоят из дефиса и одного символа. Регистр букв в имени имеет значение. Модули могут регистрировать дополнительные унарные операторы.
| Имя | Описание | Ограниченный |
|---|---|---|
-d | Аргумент рассматривается как имя файла. Истина, если файл существует и является каталогом | да |
-e | Аргумент рассматривается как имя файла. Истина, если файл (или каталог, или специальный файл) существует | да |
-f | Аргумент рассматривается как имя файла. Истина, если файл существует и является обычным файлом | да |
-s | Аргумент рассматривается как имя файла. Истина, если файл существует и не пуст | да |
-L | Аргумент рассматривается как имя файла. Истина, если файл существует и является символической ссылкой | да |
-h | Аргумент рассматривается как имя файла. Истина, если файл существует и является символической ссылкой (то же, что и -L) |
да |
-F | Истина, если строка задаёт существующий файл, доступный с учётом всех настроенных в данный момент правил контроля доступа сервера для этого пути. Для проверки используется внутренний подзапрос, поэтому применяйте оператор с осторожностью: он может повлиять на производительность сервера! | |
-U | Истина, если строка задаёт допустимый URL, доступный с учётом всех настроенных в данный момент правил контроля доступа сервера для этого пути. Для проверки используется внутренний подзапрос, поэтому применяйте оператор с осторожностью: он может повлиять на производительность сервера! | |
-A | Псевдоним для -U
|
|
-n | Истина, если строка не пуста | |
-z | Истина, если строка пуста | |
-T | Ложь, если строка пуста, равна "0", "off", "false" или "no" (без учёта регистра). В противном случае — истина. |
|
-R | То же, что и "%{REMOTE_ADDR} -ipmatch ...", но работает эффективнее |
Операторы, отмеченные как «ограниченные», недоступны в некоторых модулях, например mod_include.
Функции
Обычные функции, возвращающие строковое значение, принимают одну строку в качестве аргумента и возвращают строку. Регистр букв в именах функций не учитывается. Модули могут регистрировать дополнительные функции.
| Имя | Описание | Особые примечания |
|---|---|---|
req, http
| Получить заголовок HTTP-запроса; имена заголовков могут добавляться в заголовок Vary, см. ниже | |
req_novary | То же, что и req, но имена заголовков не добавляются в заголовок Vary |
|
resp | Получить заголовок HTTP-ответа (большинство заголовков ответа ещё не будут установлены во время <If>) |
|
reqenv | Получить переменную окружения запроса (для краткости к переменным также можно обращаться с помощью v). | порядок выполнения |
osenv | Получить переменную окружения операционной системы | |
note | Получить заметку запроса | порядок выполнения |
env | Вернуть первое совпадение из note, reqenv, osenv
|
порядок выполнения |
tolower | Преобразовать строку в нижний регистр | |
toupper | Преобразовать строку в верхний регистр | |
escape | Экранировать специальные символы в кодировке %hex | |
unescape | Снять экранирование строки в кодировке %hex, оставляя закодированные косые черты без изменений; вернуть пустую строку, если найдено %00 | |
base64 | Закодировать строку в формате base64 | |
unbase64 | Декодировать строку в формате base64; вернуть строку, обрезанную при обнаружении 0x00 | |
md5 | Вычислить хеш строки с помощью MD5, затем представить хеш в шестнадцатеричном формате | |
sha1 | Вычислить хеш строки с помощью SHA1, затем представить хеш в шестнадцатеричном формате | |
file | Прочитать содержимое файла (включая символы конца строки, если они есть) | ограничена |
filesize | Вернуть размер файла (или 0, если файл не существует или не является обычным файлом) | ограничена |
ldap | Экранировать символы в соответствии с правилами экранирования отличительных имён LDAP (RFC4514) и фильтров LDAP (RFC4515). (Доступно в httpd версии 2.4.53 и новее) |
Функции, отмеченные как «ограниченные» в последнем столбце, недоступны в некоторых модулях, например mod_include.
При использовании функций, отмеченных как «порядок выполнения» в последнем столбце, следует учитывать порядок выполнения различных компонентов сервера, особенно если функция используется в директиве <If>, которая выполняется на относительно раннем этапе.
Порядок обработки переменных окружения
При поиске переменных окружения в условии <If> важно учитывать, что разрешение переменных происходит на очень раннем этапе обработки запроса. Как правило, директивы, заданные вне контекста виртуального хоста (в контексте каталога, расположения или htaccess), к этому моменту ещё не успевают выполниться. SetEnvIf в области видимости виртуального хоста — одна из директив, выполняющихся до этого разрешения Если
reqenv используется вне <If>, разрешение обычно происходит позже, но точный момент зависит от директивы, в которой используется выражение. При использовании функций req или http имя заголовка автоматически добавляется в заголовок Vary ответа HTTP, за исключением случаев, отдельно отмеченных для директивы, принимающей выражение. Чтобы предотвратить добавление имён в заголовок Vary, можно использовать функцию req_novary.
Помимо функций, возвращающих строковое значение, существуют функции, возвращающие списки: они принимают одну строку в качестве аргумента и возвращают список слов, то есть список строк. Список слов можно использовать со специальным оператором -in. Регистр букв в именах функций не учитывается. Модули могут регистрировать дополнительные функции.
Встроенных функций, возвращающих списки, нет. mod_ssl предоставляет PeerExtList. Подробности см. в описании SSLRequire (однако PeerExtList также можно использовать вне SSLRequire).
Примеры выражений
В следующих примерах показано, как можно использовать выражения для проверки запросов:
# Compare the host name to example.com and redirect to www.example.com if it matches
<If "%{HTTP_HOST} == 'example.com'">
Redirect permanent "/" "http://www.example.com/"
</If>
# Force text/plain if requesting a file with the query string contains 'forcetext'
<If "%{QUERY_STRING} =~ /forcetext/">
ForceType text/plain
</If>
# Only allow access to this content during business hours
<Directory "/foo/bar/business">
Require expr %{TIME_HOUR} -gt 9 && %{TIME_HOUR} -lt 17
</Directory>
# Check a HTTP header for a list of values
<If "%{HTTP:X-example-header} in { 'foo', 'bar', 'baz' }">
Header set matched true
</If>
# Check an environment variable for a regular expression, negated.
<If "! reqenv('REDIRECT_FOO') =~ /bar/">
Header set matched true
</If>
# Check result of URI mapping by running in Directory context with -f
<Directory "/var/www">
AddEncoding x-gzip gz
<If "-f '%{REQUEST_FILENAME}.unzipme' && ! %{HTTP:Accept-Encoding} =~ /gzip/">
SetOutputFilter INFLATE
</If>
</Directory>
# Check against the client IP
<If "-R '192.168.1.0/24'">
Header set matched true
</If>
# Function example in boolean context
<If "md5('foo') == 'acbd18db4cc2f85cedef654fccc4a4d8'">
Header set checksum-matched true
</If>
# Function example in string context
Header set foo-checksum "expr=%{md5:foo}"
# This delays the evaluation of the condition clause compared to <If>
Header always set CustomHeader my-value "expr=%{REQUEST_URI} =~ m#^/special_path\.php$#"
# Conditional logging
CustomLog logs/access-errors.log common "expr=%{REQUEST_STATUS} >= 400"
CustomLog logs/access-errors-specific.log common "expr=%{REQUEST_STATUS} -in {'405','410'}" Прочее
| Имя | Альтернатива | Описание |
|---|---|---|
-in | in | строка содержится в списке слов |
/regexp/ | m#regexp# | Регулярное выражение (вторая форма позволяет использовать разделители, отличные от /) |
/regexp/i | m#regexp#i | Регулярное выражение без учёта регистра |
$0 ... $9 | Обратные ссылки регулярных выражений |
Обратные ссылки регулярных выражений
Строки $0 ... $9 позволяют ссылаться на группы захвата из ранее выполненных регулярных выражений, успешно нашедших совпадение. Обычно их можно использовать только в том же выражении, что и соответствующее регулярное выражение, однако некоторые модули допускают особые варианты использования.
Сравнение с SSLRequire
Синтаксис ap_expr в основном является расширением синтаксиса устаревшей директивы SSLRequire. Различия описаны в документации SSLRequire.
История версий
Функция req_novary доступна в версии 2.4.4 и новее.
© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/expr.html