Apache HTTP Server 中的表达式

历史上,Apache HTTP Server 的不同模块中用于表达条件的表达式有多种语法变体。目前正在进行一些努力,仅对所有配置指令使用一个名为* ap_expr 的变体。本文档介绍 ap_expr *表达式解析器。

Backus-Naur 格式的语法

Backus-Naur Form(BNF)是无上下文语法的一种标记技术,通常用于描述计算中使用的语言的语法。在大多数情况下,表达式用于表示布尔值。对于这些,BNF 中的起点是expr。但是,一些伪指令,例如LogMessage接受表达式,该表达式的结果为字符串值。对于这些,BNF 的起点是string

Note

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 ")"

Variables

表达式解析器提供了许多形式为%{HTTP_HOST}的变量。注意,变量的值可能取决于对其进行评估的请求处理的阶段。例如,在完成身份验证之前,先对<If >指令中使用的表达式进行求值。因此,在这种情况下不会设置%{REMOTE_USER}

以下变量提供命名的 HTTP 请求 Headers 的值。其他 Headers 的值可以通过req function获得。使用这些变量可能会导致将 Headers 名称添加到 HTTP 响应的 Vary Headers 中,除非在接受表达式的指令中另有说明。 req_novary function可用于规避此行为。

Name
HTTP_ACCEPT
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_REFERER
HTTP_USER_AGENT

其他与请求相关的变量

Name Description
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 如果文件在LAST_MODIFIED时已由服务器确定,则以20101231235959格式对文件的最后修改日期和时间进行参考。
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 响应的 Content Type(在<If>期间不可用)
HANDLER handler创建响应的名称
HTTP2 on”(如果请求使用 http/2),否则为“ off
HTTPS 如果请求使用 https,则为“ on”,否则为“ off
IPV6 如果连接使用 IPv6,则为“ on”,否则为“ off
REQUEST_STATUS 请求的 HTTP 错误状态(在<If>期间不可用)
REQUEST_LOG_ID 请求的错误日志 ID(请参见ErrorLogFormat)
CONN_LOG_ID 连接的错误日志 ID(请参阅ErrorLogFormat)
CONN_REMOTE_ADDR 连接的对等 IP 地址(请参见mod_remoteip模块)
CONTEXT_PREFIX
CONTEXT_DOCUMENT_ROOT

Misc variables

Name Description
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

Binary operators

除某些内置比较运算符外,二进制运算符的格式为“ -[a-zA-Z][a-zA-Z0-9_]+”,即减号和至少两个字符。名称不区分大小写。模块可以注册其他二进制运算符。

Comparison operators

Name Alternative Description
== = String equality
!= String inequality
< 字符串小于
<= 字符串小于或等于
> 字符串大于
>= 字符串大于或等于
=~ 字符串匹配正则表达式
!~ 字符串与正则表达式不匹配
-eq eq Integer equality
-ne ne Integer inequality
-lt lt 整数小于
-le le 小于或等于整数
-gt gt 整数大于
-ge ge 大于或等于整数

其他二进制运算符

Name Description
-ipmatch IP 地址与地址/网络掩码匹配
-strmatch 左字符串匹配右字符串给定的模式(包含通配符*,?,[])
-strcmatch -strmatch相同,但不区分大小写
-fnmatch -strmatch相同,但斜杠与通配符不匹配

Unary operators

一元运算符采用一个参数,格式为“ -[a-zA-Z]”,即减号和一个字符。名称*区分大小写。模块可以注册其他一元运算符。

Name Description Restricted
-d 该参数被视为文件名。如果文件存在并且是目录,则为 True yes
-e 该参数被视为文件名。如果文件(或目录或特殊文件)存在则为真 yes
-f 该参数被视为文件名。如果文件存在且为常规文件,则为 True yes
-s 该参数被视为文件名。如果文件存在且不为空,则为 True yes
-L 该参数被视为文件名。如果文件存在且为符号链接,则为 true yes
-h 该参数被视为文件名。如果文件存在且为符号链接(与-L相同),则为 True。 yes
-F 如果 string 是有效文件,则为 true,可通过该路径的所有服务器当前配置的访问控制进行访问。这使用内部子请求进行检查,因此请谨慎使用-它可能会影响服务器的性能!
-U 如果 string 是有效的 URL,则为 true,可通过该路径的所有服务器当前配置的访问控制来访问。这使用内部子请求进行检查,因此请谨慎使用-它可能会影响服务器的性能!
-A -U的别名
-n 如果字符串不为空,则为真
-z 如果字符串为空则为真
-T 如果字符串为空,“ 0”,“ off”,“ false”或“ no”(不区分大小写),则为 False。否则为真。
-R 与“ %{REMOTE_ADDR} -ipmatch ...”相同,但效率更高

标记为“受限”的运算符在mod_include之类的某些模块中不可用。

Functions

普通的字符串值函数将一个字符串作为参数并返回一个字符串。函数名称不区分大小写。模块可以注册其他功能。

Name Description Special notes
req , http 获取 HTTP 请求头;Headers 名称可以添加到 Vary Headers 中,请参见下文
req_novary req相同,但 Headers 名称不会添加到 Vary Headers 中
resp 获取 HTTP 响应 Headers(大多数响应 Headers 在<If>期间尚未设置)
reqenv 查找请求环境变量(作为快捷方式,v也可用于访问变量)。 ordering
osenv 查找 os 环境变量
note 查找请求说明 ordering
env 返回第一个匹配项notereqenvosenv ordering
tolower 将字符串转换为小写
toupper 将字符串转换为大写
escape 以%hex 编码转义特殊字符
unescape 不转义%hex 编码的字符串,仅保留编码的斜杠;如果找到%00,则返回空字符串
base64 使用 base64 编码对字符串进行编码
unbase64 解码 base64 编码的字符串,如果找到 0x00,则返回截断的字符串
md5 使用 MD5 哈希字符串,然后使用十六进制编码对哈希进行编码
sha1 使用 SHA1 哈希字符串,然后使用十六进制编码对哈希进行编码
file 从文件读取内容(包括行尾,如果存在) restricted
filemod 返回文件的最后修改时间(如果文件不存在或不是常规文件,则返回 0) restricted
filesize 返回文件的大小(如果文件不存在或不是常规文件,则返回 0) restricted

在最后一栏中标记为“受限”的功能在mod_include之类的某些模块中不可用。

在最后一栏中标记为“ ordering”的功能需要对服务器的不同组件的 Sequences 进行一些考虑,尤其是在<If>指令中使用该功能时,该指令的评估相对较早。

Environment variable ordering

在<If>条件内查找环境变量时,重要的是要考虑在解决请求的过程中有多早出现这种解决方案。作为准则,在虚拟主机上下文(目录,位置,htaccess)之外定义的任何指令都不太可能有执行机会。虚拟主机范围中的SetEnvIf是在此解决方案之前运行的一个指令

在<If>之外使用reqenv时,通常会在以后解决该问题,但是确切的时间取决于在其中使用该表达式的指令。

使用函数reqhttp时,Headers 名称将自动添加到 HTTP 响应的 Vary Headers 中,除非在接受表达式的指令中另有说明。 req_novary函数可用于防止将名称添加到 Vary Headers 中。

除了字符串值函数外,还有一些列表值函数,它们将一个字符串作为参数并返回一个单词列表,即一个字符串列表。单词表可以与特殊的-in运算符一起使用。函数名称不区分大小写。模块可以注册其他功能。

没有内置的列表值函数。 mod_ssl提供PeerExtList。有关详细信息,请参见SSLRequire的描述(但SSLRequire之外也可以使用PeerExtList)。

Example expressions

以下示例说明如何使用表达式评估请求:

# 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'}"

Other

Name Alternative Description
-in in 单词表中包含的字符串
/regexp/ m#regexp# 正则表达式(第二种形式允许使用与/不同的分隔符)
/regexp/i m#regexp#i 不区分大小写的正则表达式
$0 ... $9 正则表达式反向引用

正则表达式反向引用

字符串$0 ... $9允许引用先前执行的,成功匹配正则表达式的捕获组。通常,它们只能与匹配的正则表达式在同一表达式中使用,但是某些模块允许特殊用途。

与 SSLRequire 比较

Version History

req_novary function可用于 2.4.4 和更高版本。

首页