Apache HTTP 服务器 2.4 版
从历史上看,Apache HTTP 服务器的不同模块中用于表达条件的表达式有几种语法变体。目前正在努力只使用一种名为ap_expr的变体来处理所有配置指令。本文档介绍了ap_expr表达式解析器。
ap_expr表达式旨在替换 HTTPD 中大多数其他表达式变体。例如,已弃用的 SSLRequire
表达式可以用 Require expr 替换。
<If>
<ElseIf>
<Else>
ErrorDocument
Alias
ScriptAlias
Redirect
AuthBasicFake
AuthFormLoginRequiredLocation
AuthFormLoginSuccessLocation
AuthFormLogoutLocation
AuthName
AuthType
RewriteCond
SetEnvIfExpr
Header
RequestHeader
FilterProvider
SSLRequire
LogMessage
mod_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
的文档中描述。