Apache使用 RewriteMap

本文描述了RewriteMap指令的使用,並提供了各種RewriteMap類型的示例。

RewriteMap指令定義了一個外部函數,可以在RewriteRuleRewriteCond指令的上下文中調用它來執行過於複雜的重寫,或者太專業化而不能僅通過正則運算式執行。

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:內部函數

當使用intMapType時,MapSource是可用的內部RewriteMap函數之一。模組作者可以通過使用ap_register_rewrite_mapfunc API註冊它們來提供其他內部函數。默認提供的功能是:

  • toupper:將鍵全部轉換為大寫。
  • tolower:將鍵全部轉換為小寫。
  • escape:將鍵中的特殊字元轉換為十六進制編碼。
  • unescape:將鍵中的十六進制編碼轉換回特殊字元。

將URI重定向到自身的全小寫版本 -

RewriteMap lc int:tolower
RewriteRule "(.*)" "${lc:$1}" [R]

txt:純文本映射

當使用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:隨機化純文本

當使用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:DBM哈希檔

當使用dbm的MapType時,MapSource是DBM資料庫檔的檔系統路徑,該檔包含要在映射中使用的鍵/值對。這與txt映射的工作方式完全相同,但速度要快得多,因為DBM是索引的,而文本檔則不是。這允許更快速地訪問所需的密鑰。

可以選擇指定特定的dbm類型:

RewriteMap examplemap "dbm=sdbm:/etc/apache/mapfile.dbm"

類型可以是sdbmgdbmndbmdb。但是,建議您只使用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:外部重寫程式

當使用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:SQL查詢

使用dbd或fastdbd的MapType時,MapSource是一個SQL SELECT語句,它接受單個參數並返回單個值。

需要將mod_dbd配置為指向正確的資料庫以執行此語句。

這種MapType有兩種形式。使用dbd的MapType會導致查詢與每個映射請求一起執行,而使用fastdbd會在內部緩存資料庫查找。因此,雖然fastdbd更高效,因此更快,但在重新啟動伺服器之前,它不會接受對數據庫的更改。

如果查詢返回多行,則使用結果集中的隨機行。

示例:

RewriteMap myquery "fastdbd:SELECT destination FROM rewrite WHERE source = %s"

上一篇: Apache URL重寫 下一篇: Apache認證和授權