本文描述了RewriteMap
指令的使用,並提供了各種RewriteMap
型別的範例。
RewriteMap
指令定義了一個外部函式,可以在RewriteRule
或RewriteCond
指令的上下文中呼叫它來執行過於複雜的重寫,或者太專業化而不能僅通過正規表示式執行。
RewriteMap
指令的語法如下:
RewriteMap MapName MapType:MapSource
對映名稱是您為對映指定的任意名稱,稍後將在指令中使用該名稱。引數通過以下語法傳遞給對映:
${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }
當發生這樣的構造時,查詢對映MapName
並查詢LookupKey
鍵。如果找到此鍵,則map-function
構造將由SubstValue
替換。如果未找到鍵,則如果未指定DefaultValue
,則將其替換為DefaultValue
或空字串。
例如,可以將RewriteMap
定義為:
RewriteMap examplemap "txt:/path/to/file/map.txt"
然後,可以在RewriteRule
中使用此對映,如下所示:
RewriteRule "^/ex/(.*)" "${examplemap:$1}"
如果在對映中找不到任何內容,則可以指定預設值:
RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}"
當使用int
的MapType
時,MapSource
是可用的內部RewriteMap
函式之一。模組作者可以通過使用ap_register_rewrite_mapfunc
API註冊它們來提供其他內部函式。預設提供的功能是:
toupper
:將鍵全部轉換為大寫。tolower
:將鍵全部轉換為小寫。escape
:將鍵中的特殊字元轉換為十六進位制編碼。unescape
:將鍵中的十六進位制編碼轉換回特殊字元。將URI重定向到自身的全小寫版本 -
RewriteMap lc int:tolower
RewriteRule "(.*)" "${lc:$1}" [R]
當使用txt的MapType
時,MapSource
是純文字對映檔案的檔案系統路徑,每行包含一個以空格分隔的鍵/值對。可選地,一行可以包含以#
字元開頭的注釋。
有效的文字重寫對映檔案具有以下語法:
# Comment line
MatchingKey SubstValue
MatchingKey SubstValue # comment
呼叫RewriteMap
時,將在行的第一個引數中查詢引數,如果找到則返回替換值。
例如,可以使用mapfile
將產品名稱轉換為產品ID,以便更容易記住URL,使用以下配方:
產品到ID組態如下 -
RewriteMap product2id "txt:/etc/apache2/productmap.txt"
RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
當使用Rnd的MapType時,MapSource
是純文字對映檔案的檔案系統路徑,每行包含一個鍵,一個或多個值以|
分隔。如果鍵匹配,將隨機選擇其中一個值。
例如,您可以使用以下對映檔案和指令通過反向代理在多個後端伺服器之間提供隨機負載平衡。影象被傳送到「靜態」池中的一個伺服器,而其他所有內容都被傳送到「動態」池中的一個。
Rewrite map file
##
## map.txt -- rewriting map
##
static www1|www2|www3|www4
dynamic www5|www6
組態的指令如下 -
RewriteMap servers "rnd:/path/to/file/map.txt"
RewriteRule "^/(.*\.(png|gif|jpg))" "http://${servers:static}/$1" [NC,P,L]
RewriteRule "^/(.*)" "http://${servers:dynamic}/$1" [P,L]
因此,當請求影象並且第一個規則匹配時,RewriteMap
會在map檔案中查詢字串static
,它會隨機返回一個指定的主機名,然後在RewriteRule
目標中使用。
如果希望更有可能選擇其中一個伺服器(例如,如果其中一個伺服器的記憶體多於其他伺服器,因此可以處理更多請求),只需在對映檔案中列出更多次。
static www1|www1|www2|www3|www4
當使用dbm的MapType時,MapSource是DBM資料庫檔案的檔案系統路徑,該檔案包含要在對映中使用的鍵/值對。這與txt
對映的工作方式完全相同,但速度要快得多,因為DBM是索引的,而文字檔案則不是。這允許更快速地存取所需的金鑰。
可以選擇指定特定的dbm
型別:
RewriteMap examplemap "dbm=sdbm:/etc/apache/mapfile.dbm"
型別可以是sdbm
,gdbm
,ndbm
或db
。但是,建議您只使用Apache HTTP Server提供的httxt2dbm
實用程式,因為它將使用正確的DBM庫,與構建httpd本身時使用的庫匹配。
要建立dbm檔案,請首先按照txt部分中的說明建立文字對映檔案。然後執行httxt2dbm
:
$ httxt2dbm -i mapfile.txt -o mapfile.map
然後,可以在RewriteMap
指令中參照生成的檔案:
RewriteMap mapname "dbm:/etc/apache/mapfile.map"
當使用prg的MapType時,MapSource是可執行程式的檔案系統路徑,該程式將提供對映行為。這可以是編譯的二進位制檔案,也可以是Perl或Python等解釋語言的程式。
當Apache HTTP Server啟動時,該程式啟動一次,然後通過STDIN和STDOUT與重寫引擎通訊。也就是說,對於每個對映函式查詢,它通過STDIN期望一個引數,並且應該在STDOUT上返回一個新行終止的響應字串。如果沒有相應的查詢值,則對映程式應返回四個字元的字串「NULL」以指示此情況。
如果在沒有將RewriteEngine
設定為on
的上下文中定義外部重寫程式,則不會啟動外部重寫程式。
預設情況下,外部重寫程式作為使用者:啟動httpd的組執行。這可以在UNIX系統上通過將使用者名和組名作為第三個引數以username:groupname
格式傳遞給RewriteMap來更改。
此功能使用重寫對映互斥鎖,這是與程式可靠通訊所必需的。可以使用Mutex
指令組態互斥鎖機制和鎖定檔案。
這裡顯示了一個簡單的範例,它將替換請求URI中帶下劃線的所有破折號。
重寫組態如下 -
RewriteMap d2u "prg:/www/bin/dash2under.pl" apache:apache
RewriteRule "-" "${d2u:%{REQUEST_URI}}"
dash2under.pl
#!/usr/bin/perl
$| = 1; # Turn off I/O buffering
while (<STDIN>) {
s/-/_/g; # Replace dashes with underscores
print $_;
}
使用dbd或fastdbd
的MapType時,MapSource是一個SQL SELECT語句,它接受單個引數並返回單個值。
需要將mod_dbd
組態為指向正確的資料庫以執行此語句。
這種MapType有兩種形式。使用dbd的MapType會導致查詢與每個對映請求一起執行,而使用fastdbd
會在內部快取資料庫查詢。因此,雖然fastdbd
更高效,因此更快,但在重新啟動伺服器之前,它不會接受對資料庫的更改。
如果查詢返回多行,則使用結果集中的隨機行。
範例:
RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"