ap_expr 表达式解析器

在先前版本的 Apache HTTP Server中,有几个用于表达式的语法变体用于在 Apache HTTP Server的不同模块中表达条件。 自 Apache HTTP Server 2.4.x以来,只有一个称为 ap_expr 的单一变体用于所有配置伪指令。 本文档描述了 HTTP Server中新的 ap_expr 表达式解析器。

Backus-Naur Form 表示法中的语法

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

变量

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

以下变量提供了命名为 HTTP 的请求标头的值。 可以使用 req 函数获取其他头的值 (请参阅下文)。 使用这些变量可能会导致头名称被添加到 HTTP 响应的 Vary 头中,除非接受表达式的指令另有说明。 req_novary 函数 (见下文) 可用于规避这种行为。

示例:

# 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>
表 2。 其他与请求相关的变量
名称 描述
REQUEST_METHOD 接收请求的 HTTP 方法(如 GET)
请求方案 请求 URI 的方案部分
REQUEST_URI 请求 URI 的路径部分
DOCUMENT_URI 与 REQUEST_URI 相同
请求文件名 与请求匹配的文件或脚本的完整本地文件系统路径 (如果在引用 REQUEST_FILENAME 时服务器已确定此路径)。 否则,例如在虚拟主机上下文中使用时,与 REQUEST_URI 的值相同
脚本文件名称 与 REQUEST_FILENAME 相同
最后修改 上次修改文件的日期和时间,格式为 20101231235959 ,如果在引用 LAST_MODIFIED 时服务器已确定此日期和时间。
路径信息 尾部路径名信息,请参见AcceptPathInfo
QUERY_STRING 当前请求的查询字符串
IS_SUBREQ 如果当前请求是子请求,那么为 "true" ,否则为 "false"
请求 完整请求行 (例如, "GET /index.html HTTP/1.1")
REMOTE_ADDR 远程主机的 IP 地址
remote_port 远程主机的端口
远程主机 远程主机的主机名
REMOTE_USER 已通过身份验证的用户名(如果有)(在 <If> 时不可用
远程身份 mod_ident 设置的用户名
SERVER_NAME 当前虚拟主机的 ServerName
SERVER_PORT 当前虚拟主机的服务器端口,请参阅 ServerName
服务器管理 当前虚拟主机的 ServerAdmin
服务器协议 请求使用的协议 (例如 HTTP/1.1)。 在某些类型的内部子请求中,此变量的值为。
文档根 当前虚拟主机的 DocumentRoot
AUTH_TYPE 配置的 "AuthType(例如 "basic)
内容类型 响应的内容类型(在 <If> 中不可用)
处理程序 创建响应的 处理程序 的名称
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 模块)
上下文前缀  
上下文文档根  

示例:

# Force text/plain if requesting a file with the query string contains 'forcetext'
<If "%{QUERY_STRING} =~ /forcetext/">
        ForceType text/plain
</If>
表 3. 杂项变量
名称 描述
时间 _ 年 本年度 (例如 2010 年)
时间 (TIME_MON) 当月 (01 , ... , 12)
时间-DAY 当月日 (01 , ...)
时间/小时 当前时间的小时部分 (00 , ... , 23)
时间最小值 当前时间的分钟部分
时间-SEC 当前时间的第二部分
时间 (TIME_WDAY) 星期几 (从星期天的 0 开始)
时间 格式为 20101231235959 的日期和时间
服务器软件 服务器版本字符串
API_VERSION API 版本的日期 (模块幻数)

有关更多变量信息,请参阅 HTTP Server

示例:

#  Only allow access to this content during business hours
<Directory "/www/webserver/htdocs/business">
        Require expr %{TIME_HOUR} -gt 9 && %{TIME_HOUR} -lt 17
</Directory>

二元运算符

二进制运算符的形式为"-a-zA-Z]a-zA-Z0-9_]+",即一个减号和至少两个字符。 名称不区分大小写。

表 4. 比较运算符
名称 备用 描述
== = 字符串等同性
!=   字符串不等式
<   字符串小于
<=   字符串小于或等于
>   字符串大于
>=   字符串大于或等于
=~   字符串与正则表达式匹配
!~   字符串与正则表达式不匹配
-等式 eq 整数等同性
-内 ne 整数不等式
-我不需要 lt 整数小于
-勒 le 整数小于或等于
-gt 格特 整数大于
-盖 ge 大于或等于整数
表 5。 其他二进制运算符
名称 描述
-ip匹配 IP 地址与地址/网络掩码匹配
-字符串匹配 左字符串与右字符串 (包含通配符 * ,? , []) 给出的模式匹配
-字符串匹配 与 -strmatch 相同,但不区分大小写
-fnmatch 与 -strmatch 相同,但通配符不匹配斜杠

示例:

# Compare the IP address of the remote host to 127.0.0.1/8 and redirect to localhost:8080 if it matches
<If "%{REMOTE_ADDR} -ipmatch '127.0.0.1/8'">
   Redirect permanent "/" "http://localhost:8080/"
</If>

一元运算符

一元运算符只有一个参数,形式为"-a-zA-Z]",即一个减号和一个字符。 该名称区分大小写。

表 6。 一元运算符
名称 描述 受限
-d 该参数被视为文件名。 如果该文件存在并且是目录,那么为 True
-e 该参数被视为文件名。 如果文件 (或目录或特殊) 存在,那么为 True
-f 该参数被视为文件名。 如果该文件存在并且是常规文件,那么为 True
-s 该参数被视为文件名。 如果文件存在且不为空,那么为 True
-L 该参数被视为文件名。 如果文件存在并且是符号链接,那么为 True
-h 该参数被视为文件名。 如果文件存在且为符号链接,则为 True(与-L)相同)
-F 如果字符串是有效文件,那么为 True ,可通过服务器当前为该路径配置的所有访问控制进行访问。
注: 这将使用内部子请求来执行检查,因此请谨慎使用该检查-这可能会影响服务器的性能!
 
-U 如果 string 是一个有效的 URL ,可通过服务器当前为该路径配置的所有访问控制访问,则为 True。
注: 这将使用内部子请求来执行检查,因此请谨慎使用该检查-这可能会影响服务器的性能!
 
-A -U的别名  
-n 如果字符串不为空,那么为 True  
-z 如果字符串为空,那么为 True  
-T False (如果字符串为空) , "0" , "off" , "false" 或 "no" (不区分大小写)。 否则为真。  
-R 与 "%{REMOTE_ADDR} -ipmatch ..." 相同, 但效率更高  
注: 在某些模块 (例如 mod_include ) 中,标记为 "restricted" 的运算符不可用。

示例:

# Check result of URI mapping by running in Directory context with -f
<Directory "/www/webserver/htdocs">
     AddEncoding x-gzip gz
<If "-f '%{REQUEST_FILENAME}.unzipme' && ! %{HTTP:Accept-Encoding} =~ /gzip/">
      SetOutputFilter INFLATE
</If>
</Directory>

函数

正常的字符串值函数采用一个字符串作为自变量,并返回一个字符串。 函数名不区分大小写。

表 7。 函数
名称 描述 受限 特殊注意事项
请求, HTTP 获取 HTTP 请求标头;标头名称可添加到 Vary 标头上(见下文)    
要求 与需求职位相同,但头名称不会添加到 Vary 头    
代表 获取 HTTP 响应标头(大多数响应标头在 <If> 期间尚未设置)    
列根夫 查找请求环境变量 (作为快捷方式, v 也可用于访问变量)   订购
奥森夫 查找操作系统环境变量    
注意 查找请求注释   订购
env 返回注释, reqenv 和 osenv 的第一个匹配项   订购
tolower 将字符串转换为小写    
toupper 将字符串转换为大写    
转义 对 %hex 编码中的特殊字符进行转义    
unescape 取消对 %hex 编码字符串的转义,仅保留编码斜杠; 如果找到 %00 ,那么返回空字符串    
base64 使用 base64 编码对字符串进行编码    
unbase64 解码 base64 编码的字符串,如果找到 0x00 ,那么返回截断的字符串    
md5 使用 MD5对字符串进行散列,然后使用十六进制编码对散列进行编码    
sha1 使用 SHA1对字符串进行散列,然后使用十六进制编码对散列进行编码    
文件 从文件中读取内容 (包括行尾,如果存在) 受限
菲勒莫德 返回文件的上次修改时间 (如果文件不存在或不是常规文件,那么返回 0)   受限
Filesize 文件的返回大小 (如果文件不存在或不是常规文件,那么返回 0) 受限
注: 在最后一列中标记为 "受限" 的函数在某些模块 (例如 mod_include) 中不可用。

在最终列中标记为 "排序" 的函数需要对服务器的不同组件进行排序进行一些考虑,尤其是当在相对早期求值的 <If> 伪指令中使用该函数时。

环境变量排序

<If> 条件中查找环境变量时,请务必考虑请求处理中发生此解析的非常早的时间。 作为准则,在虚拟主机上下文 (目录,位置, htaccess) 外部定义的任何伪指令都不可能还没有执行的机会。 虚拟主机作用域中的SetEnvIf是在该决议之前运行的一条指令。

<If>外部使用 reqenv 时,通常稍后会发生解析,但确切的计时取决于已在其中使用表达式的伪指令。

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

除了字符串值函数之外,还有列表值函数以一个字符串作为参数并返回一个 wordlist ,即一个字符串列表。 可将 wordlist 与特殊的 in 运算符一起使用 (请参阅下文)。 函数名不区分大小写。 没有内置列表值函数。

示例:


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

其他

表 8。 其他
名称 备用 描述
入门 包含在 wordlist 中的字符串
/regexp/ m#regexp# 正则表达式 (第二种形式允许与/不同的定界符)
/regexp/i #regexp#i 不区分大小写的正则表达式
$0... $9   正则表达式反向引用
注: 字符串 $0 ... $9 允许引用先前执行的成功匹配正则表达式中的捕获组。 它们通常只能在与匹配正则表达式相同的表达式中使用,但某些模块允许特殊使用。

示例:

# Check a HTTP header for a list of values
<If "%{HTTP:X-example-header} in { 'foo', 'bar', 'baz' }">
     Header set matched true
</If>