ap_expr 表示式剖析器

在舊版 Apache HTTP Server中,表示式有數個語法變式,用來表示 Apache HTTP Server的不同模組中的條件。 從 Apache HTTP Server 2.4.x開始,只有一個單一變式,稱為用於所有配置指引的 ap_expr。 本文件說明 HTTP Server中的新 ap_expr 表示式剖析器。

巴科斯-瑙爾形式記法中的文法

Backus-Naur 形式 (BNF) 是上下文無關文法的一種表示法技術,通常用來說明計算中使用的語言語法。 在大部分情況下,表示式用來表示布林值。 對於這些, BNF 中的起始點是 expr。 不過,少數指引接受求值為字串值的表示式。 對於那些, BNF 中的起始點是字串。

變數

表示式剖析器提供許多格式為%{HTTP_HOST}的變數。 請注意,變數值可能取決於評估它的要求處理程序階段。 For example, an expression used in an <If> directive is evaluated before authentication is done. 因此,在此情況下將不會設定%{REMOTE_USER} 。

下列變數提供具名 HTTP 要求標頭的值。 其他標頭的值可以使用 req 函數取得 (請參閱下面的說明)。 使用這些變數可能會導致將標頭名稱新增至 HTTP 回應的「改變」標頭,但接受表示式之指引的其他附註除外。 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 送入要求 (例如 GET) 的 HTTP 方法
REQUEST_SCHEME 要求 URI 的架構部分
REQUEST_URI 要求 URI 的路徑部分
文件 _ URI 與 REQUEST_URI 相同
要求檔名 符合要求之檔案或 Script 的完整本端檔案系統路徑 (如果伺服器在參照 REQUEST_FILENAME 時已確定的話)。 否則,例如在虛擬主機環境定義中使用時,與 REQUEST_URI 的值相同
SCRIPT_FILENAME 與 REQUEST_FILENAME 相同
前次修改時間 檔案前次修改的日期和時間,格式為 20101231235959 (如果參照 LAST_MODIFIED 時已由伺服器決定)。
路徑資訊 尾端路徑名稱資訊,請參閱 AcceptPathInfo
QUERY_STRING 現行要求的查詢字串
IS_SUBREQ 如果現行要求是子要求,則為 "true"; 否則為 "false"
THE_REQUEST 完整要求行 (例如 ,"GET /index.html HTTP/1.1")
REMOTE_ADDR 遠端主機的 IP 位址
遠端埠 遠端主機的埠
遠端主機 遠端主機的主機名稱
REMOTE_USER The name of the authenticated user, if any (not available during <If>)
遠端代理程式 mod_ident 設定的使用者名稱
SERVER_NAME 現行虛擬主機的 ServerName
SERVER_PORT 現行虛擬主機的伺服器埠,請參閱 ServerName
伺服器 _ 管理者 現行虛擬主機的 ServerAdmin
SERVER_PROTOCOL 要求所使用的通訊協定 (例如 HTTP/1.1)。 在部分類型的內部子要求中,此變數具有值 INCLUDED。
文件 _ 根目錄 現行虛擬主機的 DocumentRoot
AUTH_TYPE 所配置的 AuthType(例如: "basic")
CONTENT_TYPE The content type of the response (not available during <If>)
處理程式 建立回應的 處理程式 名稱
HTTPS) "on" 如果要求使用 https , "off" 否則
IPV6 如果連線使用 IPv6,則為 "on"; 否則為 "off"
要求狀態 The HTTP error status of the request (not available during <If>)
要求 LOG_ID 要求的錯誤日誌 ID (請參閱 ErrorLog格式)
CONN_LOG_ID 連線的錯誤日誌 ID (請參閱 ErrorLog格式)
CONN_REMOTE_ADDR 連線的對等節點 IP 位址 (請參閱 mod_remoteip 模組)
環境定義 _ 字首  
CONTEXT_DOCUMENT_ROOT  

範例:

# Force text/plain if requesting a file with the query string contains 'forcetext'
<If "%{QUERY_STRING} =~ /forcetext/">
        ForceType text/plain
</If>
表 3. 細項變數
名稱 說明
TIME_YEAR 本年度 (例如 2010 年)
TIME_MON 現行月份 (01 , ... , 12)
天 (TIME_DAY) 現行日期 (01 , ...)
TIME_HOUR 現行時間的小時部分 (00 , ... , 23)
TIME_MIN 現行時間的分鐘部分
TIME_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 eq 整數相等
-沒有 ne 整數不等式
-是 lt 整數小於
-勒 LE 小於或等於整數
-gt gt 整數大於
-格 GE 大於或等於的整數
表 5. 其他二進位運算子
名稱 說明
-ipmatch IP 位址符合位址/網路遮罩
-strmatch 左字串符合右字串給定的型樣 (包含萬用字元 *、?、[])
-strcmatch 與 -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 引數被視為檔名。 如果檔案存在且是符號鏈結 (與 -L 相同) ,則為 True
-F 如果字串是有效的檔案,則為 true ,可透過該路徑的所有伺服器目前配置的存取控制來存取。
附註: 這會使用內部子要求來執行檢查,因此請小心使用它-它可能會影響您伺服器的效能!
 
-U 如果字串是有效的 URL ,則為 true ,可透過該路徑的所有伺服器目前配置的存取控制來存取。
附註: 這會使用內部子要求來執行檢查,因此請小心使用它-它可能會影響您伺服器的效能!
 
-A -U 的別名  
-n 如果字串不是空的,則為 True  
-z 如果字串是空的,則為 True  
-T False 表示字串是空的、"0"、"off"、"false" 或 "no" (不區分大小寫)。 否則為 true。  
-R 與 "%{REMOTE_ADDR} -ipmatch ..." 相同, 但更有效率  
附註: 標示為「受限」的運算子在某些模組中無法使用,例如 mod_include

範例:

# 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. 功能
名稱 說明 限制 特殊注意事項
req、http 取得 HTTP 要求標頭; 標頭名稱可以新增至 Vary 標頭 (請參閱下面的說明)    
req_novary 與 req 相同,但標頭名稱將不會新增至 Vary 標頭    
回應 Get HTTP response header (most response headers will not yet be set during <If>)    
reqenv 查閱要求環境變數 (作為捷徑, v 也可以用來存取變數)   訂購
奧森夫 查閱作業系統環境變數    
附註 查閱要求附註   訂購
環境 傳回 note、reqenv、osenv 的第一個相符項   訂購
tolower 將字串轉換成小寫    
toupper 將字串轉換為大寫    
escape 以 %hex 編碼跳出特殊字元    
unescape 取消跳出 %hex 編碼字串,只保留已編碼的斜線; 如果找到 %00 ,則傳回空字串    
base64 使用 base64 編碼來編碼字串    
unbase64 解碼 base64 編碼字串,如果找到 0x00 ,則傳回截斷的字串    
md5 使用 MD5來雜湊字串,然後使用十六進位編碼來編碼雜湊    
sha1 使用 SHA1來雜湊字串,然後使用十六進位編碼來編碼雜湊    
檔案 從檔案讀取內容 (包括行尾,當存在時) 受限
菲萊莫德 傳回檔案的前次修改時間 (如果檔案不存在或不是一般檔案,則傳回 0)   受限
檔案大小 檔案的傳回大小 (如果檔案不存在或不是一般檔案,則為 0) 受限
附註:mod_include之類的部分模組中,無法使用最終直欄中標示為「受限」的函數。

在最終直欄中標示為「排序」的函數需要考量伺服器不同元件的排序,尤其是在 <If> 指引內使用該函數時,該函數會在相對較早的評估中使用。

環境變數排序

<If> 條件內查閱環境變數時,請務必考量此解決方案在處理要求時的極早期。 作為準則,在虛擬主機環境定義之外定義的任何指引 (目錄、位置、htaccess) 可能還沒有機會執行。 SetEnv如果虛擬主機範圍中的 是在此解析之前執行的指引。

<If>外部使用 reqenv 時,解決方案通常會在稍後發生,但確切的計時取決於在其中使用表示式的指引。

使用函數 req 或 http 時,標頭名稱會自動新增至 HTTP 回應的 Vary 標頭,但接受表示式之指引的其他附註除外。 req_novary 函數可用來防止名稱新增至 Vary 標頭。

除了字串值函數之外,還有以一個字串作為引數並傳回字組清單 (即字串清單) 的清單值函數。 字組清單可以與特殊 -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 m#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>