Apache HTTP 伺服器版本 2.4
此文件補充 mod_rewrite
參考文件。它說明 RewriteMap
指令的用法,並提供範例說明每種類型的 RewriteMap
。
在 RewriteRule
或 RewriteCond
指令的架構中可呼叫 RewriteMap
指令定義的外部函數,以進行太複雜或太特殊,單單以正規表示式無法執行的重寫作業。此查詢的來源可以是下方各節所列的類型,或列於 RewriteMap
參考文件的類型。
以下是 RewriteMap
指令的語法
RewriteMap MapName MapType:MapSource
您所指定指定的地圖任意名稱為 MapName,您將在後續指令中使用此名稱。參數透過下列語法傳遞至地圖
${
MapName :
LookupKey }
${
MapName :
LookupKey |
DefaultValue }
當出現這樣的建構時,系統會檢閱地圖 MapName 然後查詢金鑰 LookupKey。如果找到金鑰,會用 SubstValue 取代地圖功能建構。如果找不到金鑰,則會用 DefaultValue 取代,如果沒有指定 DefaultValue,則會用空字串取代。
例如,您可以定義 RewriteMap
為
RewriteMap examplemap "txt:/path/to/file/map.txt"
然後您便可以在 RewriteRule
中使用這個地圖,如下所示
RewriteRule "^/ex/(.*)" "${examplemap:$1}"
如果在映射中找不到任何東西,則可以指定預設值
RewriteRule "^/ex/(.*)" "${examplemap:$1|/not_found.html}"
無法在 RewriteMap
指令中使用 <Directory>
區段或 .htaccess
檔案。您必須在伺服器或虛擬主機環境中宣告這個映射。在建立映射之後,您可以在這些範圍中,在您的 RewriteRule
以及 RewriteCond
指令中使用這個映射。不過您無法在這些範圍中**宣告**它。
以下各節將說明可以使用的各種 MapType,並提供各類型的範例。
當使用 int
的 MapType 時,MapSource 是其中一個可用的內部 RewriteMap
函式。模組作者可以使用 ap_register_rewrite_mapfunc
API 註冊額外內部函數。預設提供的函式為
如要使用其中一個函式,請建立一個引用 int 函式的 RewriteMap
,然後在 RewriteRule
中使用該映射。
將 URI 重新導向至其全小寫版本
RewriteMap lc int:tolower RewriteRule "(.*)" "${lc:$1}" [R]
請注意,這裡提供的範例僅供說明用途,並不構成建議。如果您想要讓 URL 不分大小寫,請考慮改用 mod_speling
。
當使用 txt
的 MapType 時,MapSource 是純文字對應檔案的檔案系統路徑,其中每列包含一個以空格分隔的金鑰/值對。有時候,列可能包含註解,以「#」字元開頭。
有效的文字重新寫入對應檔案將具有以下語法
#註解列
相符金鑰 取代值
相符金鑰 取代值 # 註解
當呼叫 RewriteMap
時,會在第一個參數行中尋找參數,如果找到,會傳回取代值。
例如,我們可以使用 mapfile 將產品名稱轉換為產品 ID,以便更輕鬆地記住 URL,如下食譜所示
產品對 ID 設定
RewriteMap product2id "txt:/etc/apache2/productmap.txt" RewriteRule "^/product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
這裡我們假設 `prods.php` 指令碼知道在查詢對應表中找不到產品時,收到 `id=NOTFOUND` 參數時該怎麼辦。
檔案 `/etc/apache2/productmap.txt` 然後包含下列內容
##
## productmap.txt - 產品對 ID 對應表檔
##
television 993
stereo 198
fishingrod 043
basketball 418
telephone 328
因此,當要求 `http://example.com/product/television` 時,會套用 RewriteRule
,並將要求內部對應到 `prods.php?id=993`。
RewriteRule "^product/(.*)" "/prods.php?id=${product2id:$1|NOTFOUND}" [PT]
查詢金鑰會由 httpd 快取,直到 mapfile 的 `mtime` (修改時間) 變更,或 httpd 伺服器重新啟動。這可以確保在許多要求呼叫的對應表上,有更好的效能。
當使用 `rnd` 的 MapType 時,MapSource 是平文件對應表檔案的檔案系統路徑,其每一行都包含一個金鑰,以及一個或多個由 `|` 分隔的值。如果金鑰相符,其中一個值將隨機選取。
例如,您可以使用下列對應表檔案和指令,透過反向代理在多個後端伺服器之間提供隨機負載平衡。圖像會傳送到「static」池中的其中一個伺服器,而其他所有內容會傳送到「dynamic」池中的其中一個伺服器。
##
## map.txt -- 重寫對應表
##
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
會在對應表檔案中查詢字串 `static`,它會隨機傳回指定的其中一個主機名稱,然後在 RewriteRule
目標中使用。
如果您希望其中一台伺服器更有可能被選取(例如,如果其中一台伺服器比其他伺服器有更多記憶體,因此可以處理更多要求),只要在對應表檔案中列出更多次即可。
靜態 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"
請注意,對於某些 dbm 類型,會產生多個檔案,且具有共同的基礎檔名。例如,你可能會有兩個名為 mapfile.map.dir
和 mapfile.map.pag
的檔案。這是正常的,你只要在 RewriteMap
指示中使用基礎檔名 mapfile.map
即可。
查詢金鑰會由 httpd 快取,直到 mapfile 的 `mtime` (修改時間) 變更,或 httpd 伺服器重新啟動。這可以確保在許多要求呼叫的對應表上,有更好的效能。
當使用 prg
的 MapType 時,MapSource 是可執行程式的檔案系統路徑,該程式將提供對應行為。這可以是編譯的二進制檔案或使用 Perl 或 Python 等直譯語言編寫的程式。
此程式在 Apache HTTP Server 啟動時啟動一次,然後透過 STDIN
和 STDOUT
與重寫引擎通訊。也就是說,對於每個對應函數查詢,它都透過 STDIN
接收一個引數,並且應該在 STDOUT
上傳回一個換行終止的回應字串。如果沒有對應的查詢值,對應程式應傳回四個字母的字串「NULL
」以表示這一點。
如果外部重寫程式是在未設定 RewriteEngine
為 on
的內容中定義,則不會啟動這些程式。
預設情況下,外部重寫程式以啟動 httpd 的使用者:群組身分執行。這可以在 UNIX 系統上變更,方法是以 username:groupname
格式將使用者名稱和群組名稱作為第三個引數傳遞給 RewriteMap
。
此功能使用 rewrite-map
mutex,這對於與程式可靠通訊是必要的。mutex 機制和鎖定檔案可以使用 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"
查詢名稱會傳遞給資料庫驅動程式作為 SQL 準備陳述式的標籤,因此需要遵循資料庫要求的所有規則(例如區分大小寫)。
RewriteMap
指令可以出現多次。對於每個對應函數,請使用一個 RewriteMap
指令來宣告其重寫對應檔案。
儘管你無法在目錄中宣告對應(`.htaccess` 檔案或 <Directory>
區塊),但有可能在目錄中使用這個對應。