Apache 中的表达式
从历史上看,有几种表达式的语法变体用于表示 Apache HTTP Server 的不同模块中的条件。目前正在努力仅为所有 configuration 指令使用一个名为 ap_expr 的变体。本文档描述了 ap_expr 表达式解析器。
ap_expr 表达式旨在替换 HTTPD 中的大多数其他表达式变体。对于 example,不推荐使用的SSLRequire表达式可以替换为要求 expr。
语法 Backus-Naur 表格符号
Backus-Naur 表格(BNF)是 context-free 语法的表示法技术,通常用于描述计算中使用的语言的语法。在大多数情况下,表达式用于表示 boolean 值。对于这些,BNF 的起点是expr
。但是,像LogMessage这样的一些指令会接受求值为 string value 的表达式。对于那些人来说,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}
形式的变量。请注意,变量的 value 可能取决于评估它的请求处理的阶段。对于 example,在完成身份验证之前会评估<If >
指令中使用的表达式。因此,在这种情况下不会设置%{REMOTE_USER}
。
以下变量提供了命名的 HTTP 请求 headers 的值。可以使用req
功能获取其他 headers 的值。使用这些变量可能会导致 header name 被添加到 HTTP 响应的 Vary 标头中,除非接受表达式的指令另有说明。req_novary
功能可用于规避此行为。
名称 |
HTTP_ACCEPT |
HTTP_COOKIE |
HTTP_FORWARDED |
HTTP_HOST |
HTTP_PROXY_CONNECTION |
HTTP_REFERER |
HTTP_USER_AGENT |
其他请求相关变量
名称 | 描述 |
REQUEST_METHOD | 传入请求的 HTTP 方法(e.g.GET ) |
REQUEST_SCHEME | 请求的 URI 的 scheme 部分 |
REQUEST_URI | 请求的 URI 的路径部分 |
DOCUMENT_URI | 与REQUEST_URI 相同 |
REQUEST_FILENAME | 如果已经由 time REQUEST_FILENAME 处的服务器确定了该请求的文件或脚本的完整本地文件系统路径,则引用该路径。否则,例如在虚拟 host context 中使用时,_val与REQUEST_URI 相同 |
SCRIPT_FILENAME | 与REQUEST_FILENAME 相同 |
LAST_MODIFIED | 如果已经由 time LAST_MODIFIED 处的服务器确定,则以20101231235959 格式对文件进行最后修改的 date 和 time 被引用。 |
SCRIPT_USER | 脚本所有者的用户 name。 |
SCRIPT_GROUP | 脚本 group 的 group name。 |
PATH_INFO | 尾随路径 name 信息,请参阅中的 AcceptPathInfo |
QUERY_STRING | 查询当前请求的 string |
IS_SUBREQ | “true ”如果当前请求是子请求,否则为“false ” |
THE_REQUEST | 完整的请求 line(e.g.,“GET /index.html HTTP/1.1 ”) |
REMOTE_ADDR | remote host 的 IP 地址 |
REMOTE_PORT | remote host 的 port(2.4.26 及更高版本) |
REMOTE_HOST | remote host 的 host name |
REMOTE_USER | 经过身份验证的用户的 name(如果有)(在<If> 期间不可用) |
REMOTE_IDENT | 由mod_ident设置的用户 name |
SERVER_NAME | 当前 vhost 的服务器名称 |
SERVER_PORT | 当前 vhost 的 server port,请参见服务器名称 |
SERVER_ADMIN | 当前 vhost 的ServerAdmin |
SERVER_PROTOCOL | 请求使用的协议 |
DOCUMENT_ROOT | 当前 vhost 的DocumentRoot |
AUTH_TYPE | 配置进行 AuthType(e.g.“basic ”) |
CONTENT_TYPE | 响应的 content type(在<If> 期间不可用) |
HANDLER | 处理器的创建响应的 name |
HTTP2 | 如果请求使用 http/2,则为“on ”,否则为“off ” |
HTTPS | 如果请求使用 https,则为“on ”,否则为“off ” |
IPV6 | 如果连接使用 IPv6 则为“on ”,否则为“off ” |
REQUEST_STATUS | 请求的 HTTP 错误状态(在<If> 期间不可用) |
REQUEST_LOG_ID | 请求的错误 log id(请参阅ErrorLogFormat) |
CONN_LOG_ID | 连接的错误 log id(请参阅ErrorLogFormat) |
CONN_REMOTE_ADDR | 连接的对等 IP 地址(参见modremoteip模块) |
CONTEXT_PREFIX | |
CONTEXT_DOCUMENT_ROOT |
其他变量
名称 | 描述 |
TIME_YEAR | 当年(e.g .2010 ) |
TIME_MON | 当前月份(01 ,...,12 ) |
TIME_DAY | 当月的当天(01 ,...) |
TIME_HOUR | 当前 time 的小时部分(00 ,...,23 ) |
TIME_MIN | 当前 time 的分钟部分 |
TIME_SEC | 当前 time 的第二部分 |
TIME_WDAY | 一周中的某一天(周日0 开头) |
TIME | 格式为20101231235959 的 date 和 time |
SERVER_SOFTWARE | 服务器 version string |
API_VERSION | API version 的 date(模块幻数) |
一些模块注册其他变量,请参见 mod_ssl。
二进制操作员
对于某些 built-in 比较 operators 的 exception,binary operators 的形式为“-[a-zA-Z][a-zA-Z0-9_]+
”,i.e。一个减号和至少两个字符。 name 不区分大小写。模块可以注册其他二进制 operators。
比较 operators
名称 | 替代 | 描述 |
== | = | String 等于 |
!= | String 不等式 | |
< | String 小于 | |
<= | String 小于或等于 | |
> | String 大于 | |
>= | String 大于或等于 | |
=~ | String 匹配正则表达式 | |
!~ | String 不匹配正则表达式 | |
-eq | eq | Integer 平等 |
-ne | ne | Integer 不等式 |
-lt | lt | Integer 小于 |
-le | le | Integer 小于或等于 |
-gt | gt | Integer 大于 |
-ge | ge | Integer 大于或等于 |
其他二进制 operators
名称 | 描述 |
-ipmatch | IP 地址匹配 address/netmask |
-strmatch | left string 匹配右 string 给出的 pattern(包含通配符*,?,[152]) |
-strcmatch | 与-strmatch 相同,但不区分大小写 |
-fnmatch | 与-strmatch 相同,但斜线与通配符不匹配 |
一元操作员
一元 operators 采用一个参数,形式为“-[a-zA-Z]
”,i.e。一个减号和一个字符。 name 区分大小写。模块可以注册其他一元运算符。
名称 | 描述 | 受限 |
-d | 该参数被视为文件名。 True 如果文件存在且是目录 | 是 |
-e | 该参数被视为文件名。 True 如果文件(或目录或特殊)存在 | 是 |
-f | 该参数被视为文件名。 True 如果文件存在且是常规文件 | 是 |
-s | 该参数被视为文件名。 True 如果文件存在且不为空 | 是 |
-L | 该参数被视为文件名。 True 如果文件存在且是符号链接 | 是 |
-h | 该参数被视为文件名。 True 如果文件存在且是符号链接(与-L 相同) | 是 |
-F | True 如果 string 是一个有效文件,可以通过该路径的所有服务器的 currently-configured 访问控制访问。这使用内部子请求来进行检查,因此请小心使用它- 它会影响服务器的 performance! | |
-U | True 如果 string 是一个有效的 URL,可以通过该路径的所有服务器的 currently-configured 访问控制访问。这使用内部子请求来进行检查,因此请小心使用它- 它会影响服务器的 performance! | |
-A | -U 的别名 | |
-n | True 如果 string 不为空 | |
-z | True 如果 string 为空 | |
-T | False 如果 string 为空,“0 ”,“off ”,“false ”或“no ”(不区分大小写)。 True 否则。 | |
-R | 与“%{REMOTE_ADDR}-ipmatch ... ”相同,但效率更高 |
标记为“受限制”的 operators 在mod_include等某些模块中不可用。
功能
普通 string-valued 函数将一个 string 作为参数,return 一个 string。函数名称不区分大小写。模块可以注册其他功能。
名称 | 描述 | 特别说明 |
req , http | 获取 HTTP 请求标头;标题名称可以添加到 Vary 标题,见下文 | |
req_novary | 与req 相同,但标题名称不会添加到 Vary 标头中 | |
resp | 获取 HTTP 响应标头(在<If> 期间,大多数响应 headers 尚未设置) | |
reqenv | 查找请求环境变量(作为快捷方式,v 也可用于访问变量)。 | ordering |
osenv | 查找操作系统环境变量 | |
note | 查询请求备注 | ordering |
env | 返回note ,reqenv ,osenv 的第一个 match | ordering |
tolower | 将 string 转换为小写 | |
toupper | 将 string 转换为大写 | |
escape | 以%十六进制编码转义特殊字符 | |
unescape | Unescape%十六进制编码 string,只留下编码斜线;如果找到%00,return empty string | |
base64 | 使用 base64 编码对 string 进行编码 | |
unbase64 | 如果找到 0x00,则解码 base64 编码的 string,return 截断的 string | |
md5 | 使用 MD5 散列 string,然后使用十六进制编码对散列进行编码 | |
sha1 | 使用 SHA1 散列 string,然后使用十六进制编码对散列进行编码 | |
file | 从文件中读取内容(包括 line 结尾,如果存在) | 限制 |
filemod | 返回文件的最后修改 time(如果文件不存在或者不是常规文件,则返回 0) | 限制 |
filesize | 返回文件的大小(如果文件不存在或者不是常规文件,则返回 0) | 限制 |
最终列中标记为“受限制”的功能在mod_include等某些模块中不可用。
在最后一列中标记为“ordering”的函数需要考虑服务器的不同组件的 ordering,尤其是在<1>指令中使用 function 时,相对较早地进行评估。
环境变量 ordering
当在<如果>条件中查找环境变量时,重要的是要考虑在此请求处理过早发生此解决方案的时间。作为指导原则,在虚拟 host context(目录,位置,htaccess)之外定义的任何指令都不太可能有机会执行。虚拟 host 范围中的SetEnvIf 之后是在此解决方案之前运行的一个指令
当在<如果>之外使用reqenv
时,分辨率通常会在稍后发生,但确切的时间取决于表达式在其中使用的指令。
当使用函数req
或http
时,标题 name 将自动添加到 HTTP 响应的 Vary 标头中,除非接受表达式的指令另有说明。req_novary
function 可用于防止将名称添加到 Vary 标头中。
除了 string-valued 函数之外,还有 list-valued 函数,它们将一个 string 作为参数并_返回一个 wordlist,i.e。 strings 列表。 wordlist 可以与特殊的-in
operator 一起使用。函数名称不区分大小写。模块可以注册其他功能。
没有 built-in list-valued 函数。 mod_ssl提供PeerExtList
。有关详细信息,请参阅SSLRequire的说明(但PeerExtList
也可在SSLRequire之外使用)。
Example 表达式
以下示例显示了如何使用表达式来评估请求:
# 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 | wordlist 中包含 string |
/regexp/ | m#regexp# | 正则表达式(第二种形式允许与/)不同的分隔符 |
/regexp/i | m#regexp#i | 不区分大小写的正则表达式 |
$0 ...$9 | 正则表达式反向引用 |
正则表达式反向引用
strings $0
...$9
允许从先前执行的,成功匹配的正则表达式中引用捕获组。它们通常只能在与匹配的正则表达式相同的表达式中使用,但某些模块允许特殊用途。
与 SSLRequire 的比较
ap_expr 语法主要是不推荐使用的SSLRequire指令语法的超集。差异在SSLRequire的文档中描述。
Version History
req_novary
功能适用于 2.4.4 及更高版本。