Пункт 21. Разбор выражений в Apache
Исторически сложилось несколько вариантов синтаксиса для выражений, используемых для выражения условия в различных модулях HTTP-сервера Apache. В настоящее время предпринимаются некоторые попытки использовать только один вариант, называемый ap_expr , для всех директив конфигурации. В этом документе описывается анализатор выражений ap_expr .
Выражение ap_expr предназначено для замены большинства других вариантов выражений в HTTPD . Например, устаревшие SSLRequire
выражения можно заменить на Require expr.
Грамматика в нотации формы Бэкуса-Наура
Форма Бэкуса-Наура (BNF) — это метод записи контекстно-свободных грамматик, часто используемый для описания синтаксиса языков, используемых в вычислениях. В большинстве случаев выражения используются для выражения логических значений. Для них отправной точкой в БНФ является expr
. Однако некоторые директивы, например, LogMessage
принимают выражения, которые оцениваются как строковое значение. Для них отправной точкой в BNF является string
.
выражение ::= " истина " | " ложный "
| " ! " выражение
| выражение " && " выражение
| выражение " || " выражение
| " ( "выражение" ) "
| комп
комп ::= строкакомп
| целочисленная комп
| унарийное слово
| слово бинарное слово
| слово " в " " { " список слов " } "
| слово " в " функции списка
| слово " =~ " регулярное выражение
| слово " !~ " регулярное выражение
stringcomp ::= слово " == " слово
| слово " != " слово
| слово " < " слово
| слово " <= " слово
| слово " > " слово
| слово " >= " слово
integercomp ::= слово " -eq " слово | слово " экв " слово
| слово " -ne " слово | слово " не " слово
| слово " -lt " слово | слово " л " слово
| слово " -ле " слово | слово " ле " слово
| слово " -gt " слово | слово " gt " слово
| слово " -ge " слово | слово " гэ " слово
список слов ::= слово
| список слов " , " слово
слово ::= слово " . " слово
| цифра
| " ' " строка " ' "
| " " " строка " " "
| переменная
| rebackref
| функция
строка ::= часть строки
| строка
часть строки ::= cstring
| переменная
| rebackref
cstring ::= ...
цифра ::= [0-9]+
переменная ::= " %{ " имя_переменной " } "
| " %{ " имя_функции " : " funcargs " } "
rebackref ::= " $ " [0-9]
функция ::= имя_функции " ( " слово " ) "
listfunction ::= listfuncname " ( " слово " ) "
Переменные
Анализатор выражений предоставляет ряд переменных формы
%{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 |
False, если строка пуста, " 0 ", " off ", " false " или " no " (без учета регистра). Правда иначе. | |
-R |
То же, что и " %{REMOTE_ADDR} -ipmatch ... ", но более эффективно
| |
Операторы, помеченные как «ограниченные», недоступны в некоторых модулях, таких как mod_include
.
Функции
Обычные строковые функции принимают одну строку в качестве аргумента и возвращают строку. Имена функций не чувствительны к регистру. Модули могут регистрировать дополнительные функции.
req , http |
Получить заголовок HTTP-запроса; имена заголовков могут быть добавлены к заголовку Vary, см. ниже | |
req_novary |
То же, что и req , но имена заголовков не будут добавляться к заголовку Vary. | |
resp |
Получить заголовок ответа HTTP | |
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 |
Чтение содержимого из файла (включая окончания строк, если они есть)
| ограниченный |
filemod |
Возвращает время последней модификации файла (или 0, если файл не существует или не является обычным файлом) | ограниченный |
filesize |
Возвращает размер файла (или 0, если файл не существует или не является обычным файлом) | ограниченный |
Функции, помеченные как «ограниченные» в последнем столбце, недоступны в некоторых модулях, таких как mod_include
.
Функции, помеченные как «упорядочивание» в последнем столбце, требуют некоторого внимания для упорядочения различных компонентов сервера, особенно когда функция используется в директиве < >, If
которая оценивается относительно рано.
Порядок переменных среды
Когда переменные среды ищутся в
If
условии < >, важно учитывать, насколько рано в обработке запроса происходит это разрешение. Как правило, любая директива, определенная вне контекста виртуального хоста (каталог, местоположение, htaccess), скорее всего, еще не успела выполниться.
SetEnvIf
в области виртуального хоста — это одна директива, которая выполняется до этого разрешения.
Когда
reqenv
используется за пределами <
If
>, разрешение обычно происходит позже, но точное время зависит от директивы, в которой использовалось выражение.
При использовании функций req
или http
имя заголовка будет автоматически добавлено к заголовку Vary ответа HTTP, если не указано иное для директивы, принимающей выражение. Эту req_novary
функцию можно использовать для предотвращения добавления имен в заголовок Vary.
В дополнение к функциям со строковым значением существуют функции со списком, которые принимают одну строку в качестве аргумента и возвращают список слов, т. е. список строк. Список слов можно использовать со специальным -in
оператором. Имена функций не чувствительны к регистру. Модули могут регистрировать дополнительные функции.
Встроенных функций со списком нет. mod_ssl
обеспечивает PeerExtList
. Подробности см. в описании
SSLRequire
(но PeerExtList
также можно использовать за пределами SSLRequire
).
Примеры выражений
В следующих примерах показано, как можно использовать выражения для оценки запросов:
# Сравните имя хоста с example.com и перенаправьте на www.example.com, если оно совпадает
<Если "%{HTTP_HOST} == 'example.com'">
Постоянная переадресация "/" "http://www.example.com/"
</Если>
# Форсировать text/plain, если запрос файла со строкой запроса содержит 'forcetext'
<Если "%{QUERY_STRING} =~ /forcetext/">
ForceType текстовый/обычный
</Если>
# Разрешить доступ к этому контенту только в рабочее время
<Каталог "/foo/bar/business">
Требовать выражение %{TIME_HOUR} -gt 9 && %{TIME_HOUR} -lt 17
</Каталог>
# Проверить заголовок HTTP на наличие списка значений
<If "%{HTTP:X-example-header} in { 'foo', 'bar', 'baz' }">
Набор заголовков соответствует истине
</Если>
# Проверить переменную окружения на регулярное выражение, инвертированное.
<Если "! reqenv('REDIRECT_FOO') =~ /bar/">
Набор заголовков соответствует истине
</Если>
# Проверить результат сопоставления URI, запустив в контексте каталога с параметром -f
<Каталог "/var/www">
AddEncoding x-gzip gz
<If "-f '%{REQUEST_FILENAME}.unzipme' && ! %{HTTP:Accept-Encoding} =~ /gzip/">
SetOutputFilter INFLATE
</Если>
</Каталог>
# Проверяем по IP клиента
<Если "-R '192.168.1.0/24'">
Набор заголовков соответствует истине
</Если>
# Пример функции в логическом контексте
<Если "md5('foo') == 'acbd18db4cc2f85cedef654fccc4a4d8'">
Контрольная сумма набора заголовков соответствует истине
</Если>
# Пример функции в строковом контексте
Заголовок установил foo-checksum "expr=%{md5:foo}"
# Это задерживает оценку предложения условия по сравнению с <If>
Заголовок всегда устанавливает мое значение CustomHeader "expr=%{REQUEST_URI} =~ m#^/special_path\.php$#"
Другой
-in |
in |
строка, содержащаяся в списке слов |
/regexp/ |
m#regexp# |
Регулярное выражение (вторая форма допускает другие разделители, чем /) |
/regexp/i |
m#regexp#i |
Регулярное выражение без учета регистра |
$0 ... $9 |
| обратные ссылки регулярных выражений |
обратные ссылки регулярных выражений
Строки $0
... $9
позволяют ссылаться на группы захвата из ранее выполненных, успешно совпадающих регулярных выражений. Обычно их можно использовать только в том же выражении, что и соответствующее регулярное выражение, но некоторые модули допускают специальное использование.
Сравнение с SSLRequire
Синтаксис ap_expr в основном представляет собой надмножество синтаксиса устаревшей SSLRequire
директивы. Различия описаны в SSLRequire
документации .
История версий
Функция req_novary
доступна для версий 2.4.4 и выше.