Apache HTTP 服务器 2.4 版

从历史上看,Apache HTTP 服务器的不同模块中用于表达条件的表达式有几种语法变体。目前正在努力只使用一种名为ap_expr的变体来处理所有配置指令。本文档介绍了ap_expr表达式解析器。
ap_expr表达式旨在替换 HTTPD 中大多数其他表达式变体。例如,已弃用的 SSLRequire 表达式可以用 Require expr 替换。

<If><ElseIf><Else>ErrorDocumentAliasScriptAliasRedirectAuthBasicFakeAuthFormLoginRequiredLocationAuthFormLoginSuccessLocationAuthFormLogoutLocationAuthNameAuthTypeRewriteCondSetEnvIfExprHeaderRequestHeaderFilterProviderSSLRequireLogMessagemod_include巴科斯-诺尔范式 (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 函数 获取其他标头的值。使用这些变量可能会导致标头名称被添加到 HTTP 响应的 Vary 标头中,除非接受表达式的指令另有说明。可以使用 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 |
请求的错误日志 ID(请参见 ErrorLogFormat) |
CONN_LOG_ID |
连接的错误日志 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 |
参数被视为文件名。如果文件存在且是目录,则为真 | yes |
-e |
参数被视为文件名。如果文件(或目录或特殊文件)存在,则为真 | yes |
-f |
参数被视为文件名。如果文件存在且是普通文件,则为真 | yes |
-s |
参数被视为文件名。如果文件存在且不为空,则为真 | yes |
-L |
参数被视为文件名。如果文件存在且是符号链接,则为真 | yes |
-h |
参数被视为文件名。如果文件存在且是符号链接,则为真(与 -L 相同) | yes |
-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 也可以用于访问变量)。 |
ordering |
osenv |
查找操作系统环境变量 | |
note |
查找请求备注 | ordering |
env |
返回 note、reqenv、osenv 的第一个匹配项 | ordering |
tolower |
将字符串转换为小写 | |
toupper |
将字符串转换为大写 | |
escape |
使用 %hex 编码转义特殊字符 | |
unescape |
取消转义 %hex 编码的字符串,保留编码的斜杠;如果找到 %00,则返回空字符串 | |
base64 |
使用 base64 编码对字符串进行编码 | |
unbase64 |
解码 base64 编码的字符串,如果找到 0x00,则返回截断的字符串 | |
md5 |
使用 MD5 对字符串进行哈希运算,然后使用十六进制编码对哈希进行编码 | |
sha1 |
使用 SHA1 对字符串进行哈希运算,然后使用十六进制编码对哈希进行编码 | |
file |
从文件读取内容(包括换行符,如果存在) | restricted |
filesize |
返回文件的大小(如果文件不存在或不是普通文件,则返回 0) | restricted |
ldap |
根据 LDAP 区分名称转义(RFC4514)和 LDAP 过滤器转义(RFC4515)的要求转义字符。 (在 httpd 2.4.53 及更高版本中可用) |
在最后一列中标记为“受限”的函数在某些模块中不可用,例如 mod_include。
在最后一列中标记为“ordering”的函数需要考虑服务器不同组件的排序,尤其是在函数在 <If> 指令中使用时,该指令在相对较早的时间进行评估。
If> 条件中查找环境变量时,重要的是要考虑此解析发生在请求处理的极早期。作为指导原则,在虚拟主机上下文(目录、位置、htaccess)之外定义的任何指令都不太可能有机会执行。虚拟主机范围内的 SetEnvIf 是在解析之前运行的一个指令reqenv 在 <If> 之外使用时,解析通常会在稍后发生,但确切时间取决于使用表达式的指令。当使用 req 或 http 函数时,头名称将自动添加到 HTTP 响应的 Vary 头中,除非接受表达式的指令另有说明。req_novary 函数可用于防止名称添加到 Vary 头中。
除了字符串值函数之外,还有列表值函数,它们接受一个字符串作为参数并返回一个词列表,即字符串列表。词列表可以与特殊的 -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 允许引用先前执行的成功匹配的正则表达式的捕获组。它们通常只能在与匹配的正则表达式相同的表达式中使用,但某些模块允许特殊用途。
ap_expr 语法主要是已弃用的 SSLRequire 指令语法的超集。差异在 SSLRequire 的文档中描述。