Apache mod_rewrite各模塊詳細(xì)介紹

關(guān)鍵詞Apache ?? mod_rewrite ?? ??????????????????????????????????????

mod_rewrite模塊

mod_rewrite模塊可以操作URL的所有部分(包括路徑信息部分), 在服務(wù)器級(jí)的(httpd.conf)和目錄級(jí)的(.htaccess)配置都有效,還可以生成最終請(qǐng)求串。此重寫(xiě)操作的結(jié)果可以是內(nèi)部子處理,也可以是外部請(qǐng)求的轉(zhuǎn)向, 甚至還可以是內(nèi)部代理處理。

? ? 但是,所有這些功能和靈活性帶來(lái)一個(gè)問(wèn)題,那就是復(fù)雜性, 因此,不要指望一天之內(nèi)就能看懂整個(gè)模塊。


內(nèi)部處理?
??? mod_rewrite模塊的內(nèi)部處理極為復(fù)雜,但是,為了使一般用戶避免犯低級(jí)錯(cuò)誤, 也讓管理員能充分利用其功能,在此仍然做一下說(shuō)明。

API程序段
首先,你必須了解,Apache是通過(guò)若干程序段來(lái)處理HTTP請(qǐng)求的。 Apache API 對(duì)每個(gè)程序段提供了一個(gè)hook程序。 Mod_rewrite使用兩個(gè)hook程序: 其一是,URL到文件名的轉(zhuǎn)譯hook,用在讀取HTTP請(qǐng)求之后,而在授權(quán)開(kāi)始之前;其二是,修正hook,用在授權(quán)程序段和讀取目錄級(jí)配置文件(.htaccess)之后, 而在內(nèi)容處理器激活之前。

所以,Apache收到一個(gè)請(qǐng)求并且確定了響應(yīng)主機(jī)(或者是虛擬主機(jī))之后,重寫(xiě)引擎即開(kāi)始執(zhí)行URL到文件名程序段,以處理服務(wù)器級(jí)的配置中所有的mod_rewrite指令。在最終數(shù)據(jù)目錄確定以后,進(jìn)入修正程序段并觸發(fā)目錄級(jí)配置中的mod_rewrite指令。這兩個(gè)程序段并不是涇渭分明的,但都實(shí)施把URL重寫(xiě)成新的URL或者文件名。 雖然API最初不是為此設(shè)計(jì)的,但它已經(jīng)成為API的一種用途,而在Apache 1.x 中這是mod_rewrite唯一的實(shí)現(xiàn)方法。 記住以下兩點(diǎn),會(huì)有助于更好地理解:

雖然mod_rewrite可以重寫(xiě)URL為URL,重寫(xiě)URL為文件名,甚至重寫(xiě)文件名為文件名,但是目前API只提供一個(gè)URL到文件名的hook。 在Apache 2.0 中,增加了兩個(gè)丟失hook以使處理過(guò)程更清晰。 但是,這樣做并沒(méi)有給用戶帶來(lái)麻煩,只需記住這樣一個(gè)事實(shí): Apache借助URL到文件名的hook而比API設(shè)計(jì)的目標(biāo)功能更強(qiáng)大。??
難以置信的是,mod_rewrite提供了目錄級(jí)的URL操作,即,.htaccess文件,而這些文件必須在URL轉(zhuǎn)換成文件名以后的較多步驟完成之后才會(huì)被處理。這也是必須的,因?yàn)?htaccess文件存在于文件系統(tǒng)中,所以處理已經(jīng)到達(dá)這個(gè)層面。換句話說(shuō),根據(jù)API程序段,這時(shí)再處理任何URL操作已經(jīng)太晚了。 為了解決這個(gè)雞和蛋的問(wèn)題,mod_rewrite使用了一個(gè)技巧:在進(jìn)行一個(gè)目錄級(jí)的URL/文件名的操作時(shí),mod_rewrite先把文件名重寫(xiě)回相應(yīng)的URL (通常這個(gè)操作是不可行的,但是參考下面的RewriteBase指令就明白它是怎么實(shí)現(xiàn)的),然后,對(duì)這個(gè)新的URL建立一個(gè)新的內(nèi)部的子請(qǐng)求,以此重新開(kāi)始API程序段的執(zhí)行。??
另外,mod_rewrite盡力使這些復(fù)雜的操作對(duì)用戶全透明,但仍須記住:服務(wù)器級(jí)的URL操作速度快而且效率高,而目錄級(jí)的操作由于這個(gè)雞和蛋的問(wèn)題速度慢效率也低。但從另一個(gè)側(cè)面看,這卻是mod_rewrite得以為一般用戶提供(局部限制的)URL操作的唯一方法。

牢記這兩點(diǎn)!

規(guī)則集的處理

當(dāng)mod_rewrite在這兩個(gè)程序段中開(kāi)始執(zhí)行時(shí),它會(huì)讀取配置結(jié)構(gòu)中的配置好的 (或者是在服務(wù)啟動(dòng)時(shí)建立的服務(wù)器級(jí)的,或者是Apache核心在遍歷目錄采集到的目錄級(jí)的)規(guī)則集,隨后,啟動(dòng)URL重寫(xiě)引擎來(lái)處理(帶有一個(gè)或多個(gè)條件)的規(guī)則集。無(wú)論是服務(wù)器級(jí)的還是目錄級(jí)的規(guī)則集,都是由同一個(gè)URL重寫(xiě)引擎處理,只是處理結(jié)果不同而已。

規(guī)則集中規(guī)則的順序是很重要的,因?yàn)橹貙?xiě)引擎是按一種特殊的(非常規(guī)的)順序處理的, 其原則是:逐個(gè)遍歷每個(gè)規(guī)則(RewriteRule directives), 如果出現(xiàn)一個(gè)匹配條件的規(guī)則,則可能回頭遍歷已有的規(guī)則條件(RewriteConddirectives)。由于歷史的原因,條件規(guī)則是置前的,所以控制流程略顯冗長(zhǎng),細(xì)節(jié)見(jiàn)Figure 1。


Figure 1:The control flow through the rewriting ruleset??

可見(jiàn),URL首先與每個(gè)規(guī)則的Pattern匹配, 如果匹配不成功,mod_rewrite立即終止此規(guī)則的處理,繼而處理下一個(gè)規(guī)則。如果匹配成功,mod_rewrite尋找響應(yīng)的規(guī)則條件,如果一個(gè)條件都沒(méi)有,則簡(jiǎn)單地用Substitution構(gòu)造的新的值來(lái)替換URL,然后繼續(xù)處理其他規(guī)則。 如果條件存在,則開(kāi)始一個(gè)內(nèi)部循環(huán)按其列出的順序逐個(gè)處理。對(duì)規(guī)則的條件的處理有所不同:URL并不與pattern匹配,而是,首先通過(guò)擴(kuò)展變量、反向引用、查找映射表等步驟建立一個(gè)TestString的字符串,隨后,用它來(lái)與CondPattern匹配。如果匹配不成功,則整個(gè)條件集和對(duì)應(yīng)的規(guī)則失敗; 如果匹配成功,則執(zhí)行下一個(gè)規(guī)則直到所有條件執(zhí)行完畢。如果所有條件得以匹配,則以Substitution替換URL,并且繼續(xù)處理。

特殊字符的引用
在Apache 1.3.20, TestString and Substitution 字符串中的特殊字符可以用前綴的斜杠來(lái)實(shí)現(xiàn)轉(zhuǎn)義(即,忽略其特殊含義而視之為普通字符)。比如,Substitution可以用'$'來(lái)包含一個(gè)美元符號(hào), 以避免mod_rewrite把它視為反向引用。

正則表達(dá)式的反向引用能力
這是很重要的一點(diǎn):一旦在Pattern或者CondPattern使用了圓括號(hào), 就會(huì)建立內(nèi)部的反向引用,可以使用$N和%N來(lái)調(diào)用(見(jiàn)下述),并且,在Substitution和TestString中都有效。 Figure 2 說(shuō)明了反向引用被轉(zhuǎn)換擴(kuò)展的位置。


Figure 2: The back-reference flow through a rule.??

雖然mod_rewrite內(nèi)部處理的這個(gè)過(guò)程是比較雜亂的, 但是了解這些可以幫助你閱讀下文中指令的講述。


環(huán)境變量
mod_rewrite 模塊會(huì)跟蹤兩個(gè)額外的(非標(biāo)準(zhǔn)的)CGI/SSI環(huán)境變量, SCRIPT_URL和SCRIPT_URI。 他們包含了當(dāng)前資源的邏輯的網(wǎng)絡(luò)
狀態(tài), 而標(biāo)準(zhǔn)的CGI/SSI變量SCRIPT_NAME和 SCRIPT_FILENAME包含的是物理的系統(tǒng)狀態(tài)。

注意: 這些變量保持的是其最初被請(qǐng)求時(shí)的URI/URL, 即, 在任何重寫(xiě)操作之前的。 其重要性在于他們是重寫(xiě)操作重寫(xiě)URL到物理路徑名的原始依據(jù)。

舉例
SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
SCRIPT_FILENAME=/u/rse/.www/index.html
SCRIPT_URL=/u/rse/
SCRIPT_URI=http://en1.engelschall.com/u/rse/?
??

實(shí)用方案
我們還提供另外一個(gè)文檔URL Rewriting Guide, 列舉了許多基于URL的問(wèn)題的實(shí)用方案,其中你可以找到真實(shí)有用的規(guī)則集和mod_rewrite的更多信息。


RewriteBase 指令
RewriteBase指令顯式地設(shè)置了目錄級(jí)重寫(xiě)的基準(zhǔn)URL。在下文中,你可以看見(jiàn)RewriteRule可以用于目錄級(jí)的配置文件中(.htaccess),并在局部范圍內(nèi)起作用,即,規(guī)則實(shí)際處理的只是剝離了本地路徑前綴的一部分。 處理結(jié)束后,這個(gè)路徑會(huì)被自動(dòng)地附著回去。默認(rèn)值是,RewriteBase physical-directory-path

在對(duì)一個(gè)新的URL進(jìn)行替換時(shí),[b:7064b9ad95]mod_rewrite模塊 [/color:7064b9ad95][/b:7064b9ad95]必須把這個(gè)URL重新注入到服務(wù)器處理中。為此,它必須知道其對(duì)應(yīng)的URL前綴或者說(shuō)URL基準(zhǔn)。通常,此前綴就是對(duì)應(yīng)的文件路徑。但是,大多數(shù)網(wǎng)站URL不是直接對(duì)應(yīng)于其物理文件路徑的,因而一般不能做這樣的假定! 所以在這種情況下,就必須用RewriteBase指令來(lái)指定正確的URL前綴。

如果你的網(wǎng)站服務(wù)器URL不是與物理文件路徑直接對(duì)應(yīng)的, 而又需要使用RewriteRule指令, 則必須在每個(gè)對(duì)應(yīng)的.htaccess文件中指定RewriteBase。??
舉例,目錄級(jí)配置文件內(nèi)容如下:

#
#??/abc/def/.htaccess -- per-dir config file for directory /abc/def
#??Remember: /abc/def is the physical path of /xyz, i.e., the server
#? ?? ?? ?? ?has a 'Alias /xyz /abc/def' directive e.g.
#
??
RewriteEngine On
??
#??let the server know that we were reached via /xyz and not
#??via the physical path prefix /abc/def
RewriteBase? ?/xyz
??
#??now the rewriting rules
RewriteRule? ?^oldstuff.html$??newstuff.html
??
上述例子中,對(duì)/xyz/oldstuff.html 的請(qǐng)求被正確地重寫(xiě)為物理的文件/abc/def/newstuff.html.

For Apache Hackers
以下列出了內(nèi)部處理的詳細(xì)步驟:

Request:
? ?/xyz/oldstuff.html
??
Internal Processing:
? ?/xyz/oldstuff.html? ???-> /abc/def/oldstuff.html??(per-server Alias)
? ?/abc/def/oldstuff.html -> /abc/def/newstuff.html??(per-dir? ? RewriteRule)
? ?/abc/def/newstuff.html -> /xyz/newstuff.html? ?? ?(per-dir? ? RewriteBase)
? ?/xyz/newstuff.html? ???-> /abc/def/newstuff.html??(per-server Alias)
??
Result:
? ?/abc/def/newstuff.html
??
雖然這個(gè)過(guò)程看來(lái)很繁復(fù),但是由于目錄級(jí)重寫(xiě)的到來(lái)時(shí)機(jī)已經(jīng)太晚了,它不得不把這個(gè)(重寫(xiě))請(qǐng)求重新注入到Apache核心中,所以Apache內(nèi)部確實(shí)是這樣處理的。但是:它的開(kāi)銷(xiāo)并不象看起來(lái)的那樣大,因?yàn)橹匦伦⑷胪耆贏pache服務(wù)器內(nèi)部進(jìn)行, 而且這樣的過(guò)程在Apache內(nèi)部也為其他許多操作所使用。所以,你可以充分信任其設(shè)計(jì)和實(shí)現(xiàn)是正確的。


RewriteCond 指令
RewriteCond指令定義了一個(gè)規(guī)則的條件,即,在一個(gè)RewriteRule指令之前有一個(gè)或多個(gè)RewriteCond指令。 條件之后的重寫(xiě)規(guī)則僅在當(dāng)前URI與pattern匹配并且符合這些條件的時(shí)候才會(huì)起作用。

TestString是一個(gè)純文本的字符串,但是還可以包含下列可擴(kuò)展的成分:

RewriteRule反向引用: 引用方法是??
$N??

(0 <= N <= 9) 引用當(dāng)前(帶有若干RewriteCond指令的)RewriteRule中的 與pattern匹配的分組成分(圓括號(hào)!)。??
RewriteCond反向引用: 引用方法是??
%N??

(1 <= N <= 9) 引用當(dāng)前若干RewriteCond條件中最后符合的條件中的分組成分(圓括號(hào)!)。??
RewriteMap 擴(kuò)展: 引用方法是??
${mapname:key|default}??

細(xì)節(jié)請(qǐng)參見(jiàn)the documentation for RewriteMap。??
服務(wù)器變量: 引用方法是??
%{ NAME_OF_VARIABLE }??

NAME_OF_VARIABLE可以是下表列出的字符串之一: HTTP headers: connection & request:? ?
HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPT
REMOTE_ADDR
REMOTE_HOST
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE
? ?
server internals: system stuff: specials:??
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQ
??

這些都對(duì)應(yīng)于類(lèi)似命名的HTTP MIME頭、Apache服務(wù)器的C變量以及Unix系統(tǒng)中的 struct tm字段,大多數(shù)都在其他的手冊(cè)或者CGI規(guī)范中有所講述。 而其中為mod_rewrite所特有的變量有:

IS_SUBREQ??
如果正在處理的請(qǐng)求是一個(gè)子請(qǐng)求,它包含字符串"true",否則就是"false"。 模塊為了解析URI中的附加文件,有可能會(huì)產(chǎn)生子請(qǐng)求。??
API_VERSION??
這是正在使用的httpd中(服務(wù)器和模塊之間內(nèi)部接口)的Apache模塊API的版本, 其定義位于include/ap_mmn.h中。mod_rewrite模塊版本對(duì)應(yīng)于正在使用的Apache的版本 (比如,在Apache 1.3.14的發(fā)行版中,這個(gè)值是19990320:10)。 通常,對(duì)它感興趣的是模塊的作者。??
THE_REQUEST??
這是由瀏覽器發(fā)送給服務(wù)器的完整的HTTP請(qǐng)求行。(比如, "GET /index.html HTTP/1.1"). 它不包含任何瀏覽器發(fā)送的附加頭信息。??
REQUEST_URI??
這是在HTTP請(qǐng)求行中所請(qǐng)求的資源。(比如上述例子中的"/index.html".)??
REQUEST_FILENAME??
這是與請(qǐng)求相匹配的完整的本地文件系統(tǒng)的文件路徑名或描述.??
特別注意事項(xiàng):

SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的,即, Apache服務(wù)器的內(nèi)部request_rec結(jié)構(gòu)中的filename字段。 第一個(gè)其實(shí)就是大家都知道的CGI變量名,而第二個(gè)則是( 包含了request_rec結(jié)構(gòu)中的uri字段的)REQUEST_URI的一個(gè)副本,??
特殊形式: %{ENV:variable} 其中的variable可以是任何環(huán)境變量。 它是通過(guò)查找Apache內(nèi)部結(jié)構(gòu)得到的, 或者(如果沒(méi)找到的話)是由Apache服務(wù)器進(jìn)程通過(guò)getenv()得到的。??
特殊形式: %{HTTP:header} 其中的header可以是任何HTTP MIME頭的名稱。 它是通過(guò)查找HTTP請(qǐng)求得到的。比如: %{HTTProxy-Connection}就是HTTP頭 ``Proxy-Connection:''的值.??
特殊形式 %{LA-U:variable} 它是一個(gè)預(yù)設(shè)的值, variable的最終值在執(zhí)行一個(gè)內(nèi)部的(基于URL的)子請(qǐng)求后決定。在重寫(xiě)需要使用一個(gè)尚未有效的但是會(huì)在之后的API程序段中設(shè)置的變量的時(shí)候,就會(huì)使用這個(gè)方法。比如,需要在服務(wù)器級(jí)配置(httpd.conf文件)中重寫(xiě)REMOTE_USER變量,則,必須使用%{LA-U:REMOTE_USER},因?yàn)榇俗兞渴怯烧J(rèn)證程序段設(shè)置的,而這個(gè)程序段是在mod_rewrite所在的URL轉(zhuǎn)譯程序段之后才執(zhí)行的。但是,因?yàn)閙od_rewrite是通過(guò)API修正程序段來(lái)實(shí)現(xiàn)目錄級(jí)(.htaccess file)配置的,而這個(gè)程序段在認(rèn)證程序段之前就執(zhí)行了,所以用%{REMOTE_USER}就可以了。??
特殊形式: %{LA-F:variable} 它是一個(gè)預(yù)設(shè)的值, variable的最終值在執(zhí)行一個(gè)內(nèi)部的(基于文件名的)子請(qǐng)求后決定。 大多數(shù)情況下和上述的LA-U是相同的.??
CondPattern是條件pattern, 即, 一個(gè)應(yīng)用于當(dāng)前實(shí)例TestString的正則表達(dá)式, 即, TestString將會(huì)被計(jì)算然后與CondPattern匹配.

謹(jǐn)記: CondPattern是一個(gè)兼容perl的正則表達(dá)式, 但是還有若干增補(bǔ):

可以在pattern串中使用'!' 字符(驚嘆號(hào))來(lái)實(shí)現(xiàn)匹配的反轉(zhuǎn)。??
CondPatterns有若干特殊的變種。除了正則表達(dá)式的標(biāo)準(zhǔn)用法,還有下列用法:??
'<CondPattern' (詞典順序的小于)
將CondPattern視為純字符串,與TestString以詞典順序相比較. 如果按詞典順序,TestString小于CondPattern,則為真.??
'>CondPattern' (詞典順序的大于)
將CondPattern視為純字符串,與TestString以詞典順序相比較. 如果按詞典順序,TestString大于CondPattern,則為真.??
'=CondPattern' (詞典順序的等于)
將CondPattern視為純字符串,與TestString以詞典順序相比較. 如果按詞典順序,TestString等于CondPattern,則為真,即,兩個(gè)字符串(逐個(gè)字符地)完全相等。如果CondPattern只是""(兩個(gè)引號(hào)), 則TestString將與空串相比較.??
'-d' (是一個(gè)目錄[directory])
將TestString視為一個(gè)路徑名并測(cè)試
它是否存在而且是一個(gè)目錄.??
'-f' (是一個(gè)常規(guī)的文件[file])
將TestString視為一個(gè)路徑名并測(cè)試它是否存在而且是一個(gè)常規(guī)的文件.??
'-s' (是一個(gè)非空的常規(guī)文件[size])
將TestString視為一個(gè)路徑名并測(cè)試它是否存在而且是一個(gè)尺寸大于0的常規(guī)的文件.??
'-l' (是一個(gè)符號(hào)連接[link])
將TestString視為一個(gè)路徑名并測(cè)試它是否存在而且是一個(gè)符號(hào)連接.??
'-F' (對(duì)子請(qǐng)求有效的業(yè)已存在的文件)
測(cè)試TestString是否一個(gè)有效的文件, 而且可以被服務(wù)器當(dāng)前已經(jīng)配置的所有存取控制所存取。 它用一個(gè)內(nèi)部子請(qǐng)求來(lái)做判斷,由于會(huì)降低服務(wù)器的性能,請(qǐng)小心使用!??
'-U' (對(duì)子請(qǐng)求有效的業(yè)已存在的URL)
測(cè)試TestString是否一個(gè)有效的URL, 而且可以被服務(wù)器當(dāng)前已經(jīng)配置的所有存取控制所存取。 它用一個(gè)內(nèi)部子請(qǐng)求來(lái)做判斷,由于會(huì)降低服務(wù)器的性能,請(qǐng)小心使用!??
注意
所有這些測(cè)試都可以用驚嘆號(hào)作前綴('!')以實(shí)現(xiàn)條件的反轉(zhuǎn).??
另外,還可以為CondPattern追加特殊的標(biāo)記

[flags]??

作為RewriteCond指令的第三個(gè)參數(shù)。 Flags是一個(gè)以逗號(hào)分隔的以下標(biāo)記的列表:

'nocase|NC' (no case)
它使測(cè)試忽略大小寫(xiě), 即, 擴(kuò)展后的TestString和CondPattern中, 'A-Z' 和'a-z'是沒(méi)有區(qū)別的。此標(biāo)記僅作用于TestString和CondPattern的比較, 而對(duì)文件系統(tǒng)和子請(qǐng)求的測(cè)試不起作用。??
'ornext|OR' (or next condition)
它以O(shè)R方式組合若干規(guī)則的條件,而不是隱含的AND。典型的例子如下:??
RewriteCond %{REMOTE_HOST}??^host1.*??[OR]
RewriteCond %{REMOTE_HOST}??^host2.*??[OR]
RewriteCond %{REMOTE_HOST}??^host3.*
RewriteRule ...some special stuff for any of these hosts...
??
如果不用這個(gè)標(biāo)記,則必須使用三個(gè) 條件/規(guī)則。??
舉例:

如果要按請(qǐng)求頭中的``User-Agent:'重寫(xiě)一個(gè)站點(diǎn)的主頁(yè),可以這樣寫(xiě):

RewriteCond??%{HTTP_USER_AGENT}??^Mozilla.*
RewriteRule??^/$? ?? ?? ?? ?? ???/homepage.max.html??[L]
??
RewriteCond??%{HTTP_USER_AGENT}??^Lynx.*
RewriteRule??^/$? ?? ?? ?? ?? ???/homepage.min.html??[L]
??
RewriteRule??^/$? ?? ?? ?? ?? ???/homepage.std.html??[L]
??
含義: 如果你使用的瀏覽器是Netscape Navigator(其識(shí)別標(biāo)志是'Mozilla'), 則你將得到內(nèi)容最大化的主頁(yè),包括Frames等等;如果你使用的是(基于終端的)Lynx,則你得到的是內(nèi)容最小化的主頁(yè),不包含tables等等;如果你使用的是其他的瀏覽器,則你得到的是一個(gè)標(biāo)準(zhǔn)的主頁(yè)。


RewriteEngine 指令
RewriteEngine指令打開(kāi)或關(guān)閉運(yùn)行時(shí)刻的重寫(xiě)引擎。 如果設(shè)置為off,則[b:7064b9ad95]mod_rewrite模塊[/color:7064b9ad95][/b:7064b9ad95]不執(zhí)行任何運(yùn)行時(shí)刻的重寫(xiě)操作, 甚至也不更新SCRIPT_URx環(huán)境變量。

使用該指令可以使[b:7064b9ad95]mod_rewrite模塊[/color:7064b9ad95][/b:7064b9ad95]無(wú)效,而無(wú)須注釋所有的RewriteRule指令!

注意:默認(rèn)情況下,重寫(xiě)配置是不可繼承的, 即,必須在每個(gè)需要的虛擬主機(jī)中設(shè)置一個(gè)RewriteEngine on指令。


RewriteLock 指令
此指令設(shè)置mod_rewrite為了和RewriteMap 程序通訊而使用的一個(gè)同步加鎖文件的名稱。 在需要使用重寫(xiě)映射表程序時(shí),它必須是一個(gè)本地路徑(而不能是一個(gè)NFS掛接設(shè)備); 對(duì)其他類(lèi)型的重寫(xiě)映射表,則無(wú)此要求。


RewriteLog 指令

RewriteLog指令設(shè)置用于記錄所有重寫(xiě)操作的文件的名稱。 如果此文件名不是以斜杠('/')開(kāi)頭,則它是相對(duì)于Server Root的。 此指令應(yīng)該僅僅出現(xiàn)在服務(wù)器級(jí)配置中。

如果要關(guān)閉對(duì)重寫(xiě)操作的記錄,不推薦把Filename設(shè)置為/dev/null,因?yàn)椋m然重寫(xiě)引擎不能輸出記錄了,但仍會(huì)內(nèi)部地建立這個(gè)日志文件, 它會(huì)使服務(wù)器速度降低,而且對(duì)管理員毫無(wú)益處! 要關(guān)閉日志,可以刪除或注解RewriteLog指令, 或者使用RewriteLogLevel 0!??
安全
參見(jiàn)Apache Security Tips,其中講述了, 為什么如果存放日志的目錄對(duì)除了啟動(dòng)服務(wù)器以外的用戶是可寫(xiě)的會(huì)帶來(lái)安全隱患。??
舉例
RewriteLog "/usr/local/var/apache/logs/rewrite.log"??


RewriteLogLevel 指令?

RewriteLogLevel指令設(shè)置重寫(xiě)引擎日志的詳細(xì)程度的級(jí)別。 默認(rèn)級(jí)別0意味著不記錄,而9或更大的值意味著記錄所有的操作。

要關(guān)閉重寫(xiě)引擎日志,可以簡(jiǎn)單地設(shè)此值為0,關(guān)閉所有的重寫(xiě)操作記錄。

使用較高的Level值會(huì)使Apache服務(wù)器速度急劇下降! 重寫(xiě)日志使用大于2的Level值只用于調(diào)試!??
舉例
RewriteLogLevel 3??


RewriteMap 指令
RewriteMap定義一個(gè)映射表, 由映射函數(shù)用于查找關(guān)鍵詞來(lái)插入/替換字段。此查找操作的源可以是多種類(lèi)型。

MapName是映射表的名稱, 指定了一個(gè)映射函數(shù),用于重寫(xiě)規(guī)則的字符串替換,它可以是下列形式之一:

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }??

如果使用了這樣的形式,則會(huì)在MapName中查找關(guān)鍵詞LookupKey。 如果找到了,則被替換成SubstValue; 如果沒(méi)有找到,則被替換成DefaultValue, 如果沒(méi)有指定DefaultValue,則被替換成空字符串。

可以使用下列MapType和MapSource的組合:

標(biāo)準(zhǔn)純文本
MapType: txt, MapSource: 有效的Unix文件系統(tǒng)文件名??
這是重寫(xiě)映射表的標(biāo)準(zhǔn)形式,即, MapSource是一個(gè)純文本文件,包含空行、注釋行(以字符'#'打頭), 以及每行一個(gè)的替換對(duì),如下。

MatchingKey SubstValue??

Example
##
##??map.txt -- rewriting map
##
??
Ralf.S.Engelschall? ? rse? ?# Bastard Operator From Hell
Mr.Joe.Average? ?? ???joe? ?# Mr. Average
??
RewriteMap real-to-user txt:/path/to/file/map.txt??

隨機(jī)純文本
MapType: rnd, MapSource: 有效的Unix文件系統(tǒng)文件名??
這個(gè)與上述的標(biāo)準(zhǔn)純文本很相似,但它有一個(gè)特殊的后處理特性: 查找完畢后,會(huì)解析其中包含的含義為``or''和``|''符號(hào)。也就是說(shuō),會(huì)隨機(jī)地選擇其中之一作為實(shí)際的返回值。 雖然這看似毫無(wú)意義,但它的設(shè)計(jì)意圖是,在一個(gè)查找值是服務(wù)器名稱的反向代理環(huán)境中,實(shí)現(xiàn)負(fù)載平衡。如:

##
##??map.txt -- rewriting map
##
??
static? ?www1|www2|www3|www4
dynamic??www5|www6
??
RewriteMap servers rnd:/path/to/file/map.txt??

散列文件
MapType: dbm[=type], MapSource: 有效的Unix文件系統(tǒng)文件名??
這里的源是一個(gè)二進(jìn)制格式的DBM文件,包含了與純文本相同的內(nèi)容, 但是因?yàn)樗袃?yōu)化的特殊表現(xiàn)形式,使它的查找速度明顯快得多。此類(lèi)型可以是sdbm, gdbm, ndbm或db,由compile-time settings所決定。如果省略type,則使用編譯時(shí)選擇的缺省設(shè)置。你可以使用任何DBM工具或者下列Perl腳本來(lái)建立這個(gè)文件,但必須保證DBM的類(lèi)型正確。 建立NDBM文件的例子:

#!/path/to/bin/perl
##
##??txt2dbm -- convert txt map to dbm format
##
??
use NDBM_File;
use Fcntl;
??
($txtmap, $dbmmap) = @ARGV;
??
open(TXT, "<$txtmap") or die "Couldn't open $txtmap!n";
tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644)
? ?or die "Couldn't create $dbmmap!n";
??
while (<TXT>) {
? ?next if (/^s*#/ or /^s*$/);
? ?$DB{$1} = $2 if (/^s*(S+)s+(S+)/);
}
??
untie %DB;
close(TXT);
??
$ txt2dbm map.txt map.db??

內(nèi)部函數(shù)
MapType: int, MapSource: 內(nèi)部的Apache函數(shù)??
這里的源是一個(gè)內(nèi)部的Apache函數(shù)。 目前,還不能由你自己建立,只能使用下列已經(jīng)存在的函數(shù):

[!--empirenews.page--]Apache mod_rewrite各模塊詳細(xì)介紹(2)[/!--empirenews.page--]

toupper:
轉(zhuǎn)換查找關(guān)鍵詞為大寫(xiě).??
tolower:
轉(zhuǎn)換查找關(guān)鍵詞為小寫(xiě).??
escape:
轉(zhuǎn)換查找關(guān)鍵詞中的特殊字符為十六進(jìn)制編碼.??
unescape:
轉(zhuǎn)換查找關(guān)鍵詞中的十六進(jìn)制編碼為特殊字符.??
外部的重寫(xiě)程序
MapType: prg, MapSource: 有效的Unix文件系統(tǒng)文件名??
這里的源是一個(gè)程序,而不是一個(gè)映射表文件。 程序的編制語(yǔ)言可以隨意選擇,但最終結(jié)果必須是可執(zhí)行的 (即, 或者是目標(biāo)代碼,或者是首行為'#!/path/to/interpreter'的腳本).

此程序僅在Apache服務(wù)器啟動(dòng)時(shí)啟動(dòng)一次, 隨后通過(guò)stdin和stdout文件句柄與重寫(xiě)引擎交互。對(duì)每個(gè)映射函數(shù)的查找操作,它從stdin接收以回車(chē)結(jié)束的查找關(guān)鍵詞, 然后把查找結(jié)果以回車(chē)結(jié)束反饋到stdout,如果查找失敗,則返回四個(gè)字符的``NULL'' (即, 對(duì)給定的關(guān)鍵詞沒(méi)有對(duì)應(yīng)的值)。 此程序的最簡(jiǎn)單形式是一個(gè)1:1的映射(即,key == value),如:

#!/usr/bin/perl
$| = 1;
while (<STDIN>) {
? ???# ...put here any transformations or lookups...
? ???print $_;
}
??
但是必須注意:

``即使它看來(lái)簡(jiǎn)單而愚蠢,只要正確,就保持原樣(Keep it simple, stupid)'' (KISS), 因?yàn)椋谝?guī)則起作用時(shí),此程序的崩潰會(huì)直接導(dǎo)致Apache服務(wù)器的崩潰。??
避免犯一個(gè)常見(jiàn)的錯(cuò)誤: 絕不要對(duì)stdout做緩沖I/O! 它會(huì)導(dǎo)致死循環(huán)! 所以上述例子中才會(huì)有``$|=1''...??
使用RewriteLock指令定義一個(gè)加鎖文件, 用于同步mod_rewrite和此程序之間的通訊。缺省時(shí)是沒(méi)有同步操作的。??
RewriteMap指令允許多次出現(xiàn)。 對(duì)每個(gè)映射函數(shù)都可以使用一個(gè)RewriteMap指令來(lái)定義其重寫(xiě)映射表。 雖然不能在目錄的上下文中定義映射表, 但是,完全可以在其中使用映射表。

注意
對(duì)于純文本和DBM格式的文件,已經(jīng)查找過(guò)的關(guān)鍵詞會(huì)被緩存在內(nèi)核中, 直到映射表的mtime改變了或者服務(wù)器重啟了。 這樣,你可以把每個(gè)請(qǐng)求都會(huì)用到的映射函數(shù)放在規(guī)則中,這是沒(méi)有問(wèn)題的,因?yàn)橥獠坎檎抑贿M(jìn)行一次!??

RewriteOptions 指令

RewriteOptions指令為當(dāng)前服務(wù)器級(jí)和目錄級(jí)的配置設(shè)置一些選項(xiàng)。 Option可以是下列值之一:

inherit??
此值強(qiáng)制當(dāng)前配置可以繼承其父配置。 在虛擬主機(jī)級(jí)配置中,它意味著主服務(wù)器的映射表、條件和規(guī)則可以被繼承。 在目錄級(jí)配置中,它意味著其父目錄的.htaccess中的條件和規(guī)則可以被繼承。??
MaxRedirects=number??
為了避免目錄級(jí)RewriteRule的無(wú)休止的內(nèi)部重定向, 在此類(lèi)重定向和500內(nèi)部服務(wù)器錯(cuò)誤次數(shù)達(dá)到一個(gè)最大值的時(shí)候, mod_rewrite會(huì)停止對(duì)此請(qǐng)求的處理。 如果你確實(shí)需要對(duì)每個(gè)請(qǐng)求允許大于10次的內(nèi)部重定向,可以增大這個(gè)值。??

RewriteRule 指令
RewriteRule指令是重寫(xiě)引擎的根本。此指令可以多次使用。 每個(gè)指令定義一個(gè)簡(jiǎn)單的重寫(xiě)規(guī)則。這些規(guī)則的定義順序尤為重要, 因?yàn)椋谶\(yùn)行時(shí)刻,規(guī)則是按這個(gè)順序逐一生效的.

Pattern是一個(gè)作用于當(dāng)前URL的兼容perl的正則表達(dá)式. 這里的``當(dāng)前''是指該規(guī)則生效時(shí)的URL的值。 它可能與被請(qǐng)求的URL不同,因?yàn)槠渌?guī)則可能在此之前已經(jīng)發(fā)生匹配并對(duì)它做了改動(dòng)。

正則表達(dá)式的一些用法:

Text:
? ?.? ?? ?? ???Any single character
? ?[chars]? ???Character class: One??of chars
? ?[^chars]? ? Character class: None of chars
? ?text1|text2 Alternative: text1 or text2
??
Quantifiers:
? ??? ?? ?? ???0 or 1 of the preceding text
? ?*? ?? ?? ???0 or N of the preceding text (N > 0)
? ?+? ?? ?? ???1 or N of the preceding text (N > 1)
??
Grouping:
? ?(text)? ?? ?Grouping of text
? ?? ?? ?? ?? ?(either to set the borders of an alternative or
? ?? ?? ?? ?? ?for making backreferences where the Nth group can??
? ?? ?? ?? ?? ?be used on the RHS of a RewriteRule with $N)
??
Anchors:
? ?^? ?? ?? ???Start of line anchor
? ?$? ?? ?? ???End? ?of line anchor
??
Escaping:
? ?char? ?? ? escape that particular char
? ?? ?? ?? ?? ?(for instance to specify the chars ".[]()" etc.)
??
更多有關(guān)正則表達(dá)式的資料請(qǐng)參見(jiàn)perl正則表達(dá)式手冊(cè)頁(yè)("perldoc perlre"). 如果你對(duì)正則表達(dá)式的更詳細(xì)的資料及其變種(POSIX regex 等.)感興趣, 請(qǐng)參見(jiàn)以下專著:

Mastering Regular Expressions
Jeffrey E.F. Friedl
Nutshell Handbook Series
O'Reilly & Associates, Inc. 1997
ISBN 1-56592-257-3


另外,在mod_rewrite中,還可以使用否字符('!')的pattern前綴,以實(shí)現(xiàn)pattern的反轉(zhuǎn)。 比如:``如果當(dāng)前URL不與pattern相匹配''. 它用于使用否pattern較容易描述的需要排除的某些情況,或者作為最后一條規(guī)則。

注意
使用否字符以反轉(zhuǎn)pattern時(shí),pattern中不能使用分組的通配成分。 由于pattern不匹配而使分組的內(nèi)容是空的,所以它是不可能實(shí)現(xiàn)的。 因此,如果使用了否pattern,那么后繼的字符串中就不能使用$N!??
重寫(xiě)規(guī)則中的Substitution是, 當(dāng)原始URL與Pattern相匹配時(shí),用以替代(或替換)的字符串。 除了純文本,還可以使用

$N 反向引用RewriteRule的pattern??
%N 反向引用最后匹配的RewriteCond pattern??
規(guī)則條件測(cè)試字符串中(%{VARNAME})的服務(wù)器變量??
映射函數(shù)調(diào)用(${mapname:key|default})??
反向引用的$N (N=0..9) 是指用Pattern所匹配的第N組的內(nèi)容去替換URL。服務(wù)器變量與RewriteCond指令的TestString相同。 映射函數(shù)由RewriteMap指令所決定,其說(shuō)明也參見(jiàn)該指令。這三種類(lèi)型變量按上面列表中的順序被擴(kuò)展。

如上所述,所有的重寫(xiě)規(guī)則都是(按配置文件中的定義順序)作用于Substitution的。 URL被Substitution完全地替換,并繼續(xù)處理直到所有規(guī)則處理完畢, 除非用L標(biāo)記顯式地終結(jié) - 見(jiàn)下文。

'-'是一個(gè)特殊的替換串,意思是不要替換! 似乎很愚蠢吧? 不, 它可以用于僅僅匹配某些URL而無(wú)須替換的情況下,即, 在發(fā)生替換前,允許以C (chain)標(biāo)記連接的多個(gè)pattern同時(shí)起作用。

還有,你甚至可以在替換字符串中新建包含請(qǐng)求串的URL。 在替換串中使用問(wèn)號(hào),以標(biāo)明其后繼的成分應(yīng)該被重新注入到QUERY_STRING中。 要?jiǎng)h除一個(gè)已有的請(qǐng)求串,可以用問(wèn)號(hào)來(lái)終結(jié)替換字符串。

注意
一個(gè)特殊功能: 在用
http://thishost[:thisport]作為替換字段的前綴時(shí), mod_rewrite會(huì)把它自動(dòng)剝離出去。 在配合生成主機(jī)名的映射函數(shù)使用的時(shí)候, 這個(gè)對(duì)隱含的外部重定向URL的精簡(jiǎn)化操作是有用的而且是重要的。 下面例子一節(jié)中的第一個(gè)例子有助于理解這點(diǎn)。??
謹(jǐn)記
由于此功能的存在,以
http://thishost為前綴的無(wú)條件外部重定向在你自己的服務(wù)器上是無(wú)效的。 要做這樣一個(gè)自身的重定向,必須使用R標(biāo)記 (見(jiàn)下文).??
此外,Substitution還可以追加特殊標(biāo)記

[flags]??

作為RewriteRule指令的第三個(gè)參數(shù)。 Flags是一個(gè)包含以逗號(hào)分隔的下列標(biāo)記的列表:??

'redirect|R [=code]' (強(qiáng)制重定向 redirect)
http://thishost[: thisport]/(使新的URL成為一個(gè)URI) 為前綴的Substitution可以強(qiáng)制性執(zhí)行一個(gè)外部重定向。如果code沒(méi)有指定,則產(chǎn)生一個(gè)HTTP響應(yīng)代碼302(臨時(shí)性移動(dòng))。如果需要使用在300-400范圍內(nèi)的其他響應(yīng)代碼,只需在此指定這個(gè)數(shù)值即可, 另外,還可以使用下列符號(hào)名稱之一: temp (默認(rèn)的), permanent, seeother. 用它可以把規(guī)范化的URL反饋給客戶端,如, 重寫(xiě)``/~''為 ``/u/'',或?qū)?u/user加上斜杠,等等。

注意: 在使用這個(gè)標(biāo)記時(shí),必須確保該替換字段是一個(gè)有效的URL! 否則,它會(huì)指向一個(gè)無(wú)效的位置! 并且要記住,此標(biāo)記本身只是對(duì)URL加上
http://thishost[:thisport]/的前綴,重寫(xiě)操作仍然會(huì)繼續(xù)。 通常,你會(huì)希望停止重寫(xiě)操作而立即重定向,則還需要使用'L'標(biāo)記.

'forbidden|F' (強(qiáng)制URL為被禁止的 forbidden)
強(qiáng)制當(dāng)前URL為被禁止的,即,立即反饋一個(gè)HTTP響應(yīng)代碼403(被禁止的)。 使用這個(gè)標(biāo)記,可以鏈接若干RewriteConds以有條件地阻塞某些URL。??
'gone|G' (強(qiáng)制URL為已廢棄的 gone)
強(qiáng)制當(dāng)前URL為已廢棄的,即,立即反饋一個(gè)HTTP響應(yīng)代碼410(已廢棄的)。 使用這個(gè)標(biāo)記,可以標(biāo)明頁(yè)面已經(jīng)被廢棄而不存在了.??
'proxy|P' (強(qiáng)制為代理 proxy)
此標(biāo)記使替換成分被內(nèi)部地強(qiáng)制為代理請(qǐng)求,并立即(即, 重寫(xiě)規(guī)則處理立即中斷)把處理移交給代理模塊。 你必須確保此替換串是一個(gè)有效的(比如常見(jiàn)的以
http://hostname開(kāi)頭的)能夠?yàn)锳pache代理模塊所處理的URI。 使用這個(gè)標(biāo)記,可以把某些遠(yuǎn)程成分映射到本地服務(wù)器名稱空間, 從而增強(qiáng)了ProxyPass指令的功能。??
注意: 要使用這個(gè)功能,代理模塊必須編譯在Apache服務(wù)器中。 如果你不能確定,可以檢查``httpd -l''的輸出中是否有mod_proxy.c。 如果有,則mod_rewrite可以使用這個(gè)功能;如果沒(méi)有,則必須啟用mod_proxy并重新編譯``httpd''程序。

'last|L' (最后一個(gè)規(guī)則 last)
立即停止重寫(xiě)操作,并不再應(yīng)用其他重寫(xiě)規(guī)則。 它對(duì)應(yīng)于Perl中的last命令或C語(yǔ)言中的break命令。這個(gè)標(biāo)記可以阻止當(dāng)前已被重寫(xiě)的URL為其后繼的規(guī)則所重寫(xiě)。 舉例,使用它可以重寫(xiě)根路徑的URL('/')為實(shí)際存在的URL, 比如, '/e/www/'.??
'next|N' (重新執(zhí)行 next round)
重新執(zhí)行重寫(xiě)操作(從第一個(gè)規(guī)則重新開(kāi)始). 這時(shí)再次進(jìn)行處理的URL已經(jīng)不是原始的URL了,而是經(jīng)最后一個(gè)重寫(xiě)規(guī)則處理的URL。 它對(duì)應(yīng)于Perl中的next命令或C語(yǔ)言中的continue命令。 此標(biāo)記可以重新開(kāi)始重寫(xiě)操作,即, 立即回到循環(huán)的頭部。
但是要小心,不要制造死循環(huán)!??
'chain|C' (與下一個(gè)規(guī)則相鏈接 chained)
此標(biāo)記使當(dāng)前規(guī)則與下一個(gè)(其本身又可以與其后繼規(guī)則相鏈接的, 并可以如此反復(fù)的)規(guī)則相鏈接。 它產(chǎn)生這樣一個(gè)效果: 如果一個(gè)規(guī)則被匹配,通常會(huì)繼續(xù)處理其后繼規(guī)則, 即,這個(gè)標(biāo)記不起作用;如果規(guī)則不能被匹配,則其后繼的鏈接的規(guī)則會(huì)被忽略。比如,在執(zhí)行一個(gè)外部重定向時(shí), 對(duì)一個(gè)目錄級(jí)規(guī)則集,你可能需要?jiǎng)h除``.www'' (此處不應(yīng)該出現(xiàn)``.www''的)。??
'type|T=MIME-type' (強(qiáng)制MIME類(lèi)型 type)
強(qiáng)制目標(biāo)文件的MIME類(lèi)型為MIME-type。 比如,它可以用于模擬mod_alias中的ScriptAlias指令, 以內(nèi)部地強(qiáng)制被映射目錄中的所有文件的MIME類(lèi)型為``application/x-httpd-cgi''.??
'nosubreq|NS' (僅用于不對(duì)內(nèi)部子請(qǐng)求進(jìn)行處理 no internal sub-request)
在當(dāng)前請(qǐng)求是一個(gè)內(nèi)部子請(qǐng)求時(shí),此標(biāo)記強(qiáng)制重寫(xiě)引擎跳過(guò)該重寫(xiě)規(guī)則。比如,在mod_include試圖搜索可能的目錄默認(rèn)文件(index.xxx)時(shí), Apache會(huì)內(nèi)部地產(chǎn)生子請(qǐng)求。對(duì)子請(qǐng)求,它不一定有用的,而且如果整個(gè)規(guī)則集都起作用,它甚至可能會(huì)引發(fā)錯(cuò)誤。所以,可以用這個(gè)標(biāo)記來(lái)排除某些規(guī)則。

根據(jù)你的需要遵循以下原則: 如果你使用了有CGI腳本的URL前綴,以強(qiáng)制它們由CGI腳本處理, 而對(duì)子請(qǐng)求處理的出錯(cuò)率(或者開(kāi)銷(xiāo))很高,在這種情況下,可以使用這個(gè)標(biāo)記。

'nocase|NC' (忽略大小寫(xiě) no case)
它使Pattern忽略大小寫(xiě),即, 在Pattern與當(dāng)前URL匹配時(shí),'A-Z' 和'a-z'沒(méi)有區(qū)別。??
'qsappend|QSA' (追加請(qǐng)求串 query string append)
此標(biāo)記強(qiáng)制重寫(xiě)引擎在已有的替換串中追加一個(gè)請(qǐng)求串,而不是簡(jiǎn)單的替換。 如果需要通過(guò)重寫(xiě)規(guī)則在請(qǐng)求串中增加信息,就可以使用這個(gè)標(biāo)記。??
'noescape|NE' (在輸出中不對(duì)URI作轉(zhuǎn)義 no URI escaping)
此標(biāo)記阻止mod_rewrite對(duì)重寫(xiě)結(jié)果應(yīng)用常規(guī)的URI轉(zhuǎn)義規(guī)則。 一般情況下,特殊字符(如'%', '$', ';'等)會(huì)被轉(zhuǎn)義為等值的十六進(jìn)制編碼。 此標(biāo)記可以阻止這樣的轉(zhuǎn)義,以允許百分號(hào)等符號(hào)出現(xiàn)在輸出中,如:??
RewriteRule /foo/(.*) /bar?arg=P1%3d$1 [R,NE]??

可以使'/foo/zed'轉(zhuǎn)向到一個(gè)安全的請(qǐng)求'/bar?arg=P1=zed'.??
'passthrough|PT' (移交給下一個(gè)處理器 pass through)
此標(biāo)記強(qiáng)制重寫(xiě)引擎將內(nèi)部結(jié)構(gòu)request_rec中的uri字段設(shè)置為 filename字段的值,它只是一個(gè)小修改,使之能對(duì)來(lái)自其他URI到文件名翻譯器的 Alias,ScriptAlias, Redirect 等指令的輸出進(jìn)行后續(xù)處理。舉一個(gè)能說(shuō)明其含義的例子: 如果要通過(guò)mod_rewrite的重寫(xiě)引擎重寫(xiě)/abc為/def,然后通過(guò)mod_alias使/def轉(zhuǎn)變?yōu)?ghi,可以這樣:??
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi??

如果省略了PT標(biāo)記,雖然mod_rewrite運(yùn)作正常, 即, 作為一個(gè)使用API的URI到文件名翻譯器,它可以重寫(xiě)uri=/abc/...為filename=/def/...,但是,后續(xù)的mod_alias在試圖作URI到文件名的翻譯時(shí),則會(huì)失效。??
注意: 如果需要混合使用不同的包含URI到文件名翻譯器的模塊時(shí), 就必須使用這個(gè)標(biāo)記。。 混合使用mod_alias和mod_rewrite就是個(gè)典型的例子。

For Apache hackers
如果當(dāng)前Apache API除了URI到文件名hook之外,還有一個(gè)文件名到文件名的hook, 就不需要這個(gè)標(biāo)記了! 但是,如果沒(méi)有這樣一個(gè)hook,則此標(biāo)記是唯一的解決方案。 Apache Group討論過(guò)這個(gè)問(wèn)題,并在Apache 2.0 版本中會(huì)增加這樣一個(gè)hook。??
'skip|S=num' (跳過(guò)后繼的規(guī)則 skip)
此標(biāo)記強(qiáng)制重寫(xiě)引擎跳過(guò)當(dāng)前匹配規(guī)則后繼的num個(gè)規(guī)則。 它可以實(shí)現(xiàn)一個(gè)偽if-then-else的構(gòu)造: 最后一個(gè)規(guī)則是then從句,而被跳過(guò)的skip=N個(gè)規(guī)則是else從句. (它和'chain|C'標(biāo)記是不同的!)??
'env|E=VAR:VAL' (設(shè)置環(huán)境變量 environment variable)
此標(biāo)記使環(huán)境變量VAR的值為VAL, VAL可以包含可擴(kuò)展的反向引用的正則表達(dá)式$N和%N。 此標(biāo)記可以多次使用以設(shè)置多個(gè)變量。這些變量可以在其后許多情況下被間接引用,但通常是在XSSI (via <!--#echo var="VAR"-->) or CGI (如 $ENV{'VAR'})中, 也可以在后繼的RewriteCond指令的pattern中通過(guò)%{ENV:VAR}作引用。使用它可以從URL中剝離并記住一些信息。??
'cookie|CO=NAME:VAL:domain[:lifetime[:path]]' (設(shè)置cookie)
它在客戶端瀏覽器上設(shè)置一個(gè)cookie。 cookie的名稱是NAME,其值是VAL。 domain字段是該cookie的域,比如'.apache.org', 可選的lifetime是cookie生命期的分鐘數(shù), 可選的path是cookie的路徑。??
注意
絕不要忘記,在服務(wù)器級(jí)配置文件中,Pattern是作用于整個(gè)URL的。 但是在目錄級(jí)配置文件中, (一般總是和特定目錄名稱相同的)目錄前綴會(huì)在pattern匹配時(shí)被自動(dòng)刪除, 而又在替換完畢后自動(dòng)被加上。此特性對(duì)很多種重寫(xiě)是必須的,因?yàn)椋绻麤](méi)有這個(gè)剝離前綴的動(dòng)作,就必須與其父目錄去匹配,而這并不總是可行的。??
但是有一個(gè)例外: 如果替換串以``http://''開(kāi)頭, 則不會(huì)附加目錄前綴, 而是強(qiáng)制產(chǎn)生一個(gè)外部重定向,或者(如果使用了P標(biāo)記)是一個(gè)代理操作!

注意
為了對(duì)目錄級(jí)配置啟用重寫(xiě)引擎,你必須在這些文件中設(shè)置``RewriteEngine On'', 并且打開(kāi)``Options FollowSymLinks'。 如果管理員對(duì)用戶目錄禁用了FollowSymLinks, 則無(wú)法使用重寫(xiě)引擎。這個(gè)限制是為了安全而設(shè)置的。??
以下是所有可能的替換組合及其含義:

在服務(wù)器級(jí)配置中(httpd.conf)
,對(duì)這樣一個(gè)請(qǐng)求 ``GET /somepath/pathinfo'':


Given Rule? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???Resulting Substitution
----------------------------------------------??----------------------------------
^/somepath(.*) otherpath$1? ?? ?? ?? ?? ?? ?? ? not supported, because invalid!
??
^/somepath(.*) otherpath$1??[R]? ?? ?? ?? ?? ???not supported, because invalid!
??
^/somepath(.*) otherpath$1??[P]? ?? ?? ?? ?? ???not supported, because invalid!
----------------------------------------------??----------------------------------
^/somepath(.*) /otherpath$1? ?? ?? ?? ?? ?? ?? ?/otherpath/pathinfo
??
^/somepath(.*) /otherpath$1 [R]? ?? ?? ?? ?? ???
http://thishost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^/somepath(.*) /otherpath$1 [P]? ?? ?? ?? ?? ???not supported, because silly!
----------------------------------------------??----------------------------------
^/somepath(.*)
http://thishost/otherpath$1? ?? ?/otherpath/pathinfo
??
^/somepath(.*)
http://thishost/otherpath$1 [R]??http://thishost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^/somepath(.*)
http://thishost/otherpath$1 [P]??not supported, because silly!
----------------------------------------------??----------------------------------
^/somepath(.*)
http://otherhost/otherpath$1? ???http://otherhost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^/somepath(.*)
http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? (the [R] flag is redundant)
??
^/somepath(.*)
http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via internal proxy
??
在/somepath的目錄級(jí)配置中
(即, 目錄/physical/path/to/somepath的.htaccess文件中包含 RewriteBase /somepath)
對(duì)這樣一個(gè)請(qǐng)求``GET /somepath/localpath/pathinfo'':


Given Rule? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???Resulting Substitution
----------------------------------------------??----------------------------------
^localpath(.*) otherpath$1? ?? ?? ?? ?? ?? ?? ? /somepath/otherpath/pathinfo
??
^localpath(.*) otherpath$1??[R]? ?? ?? ?? ?? ???
http://thishost/somepath/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^localpath(.*) otherpath$1??[P]? ?? ?? ?? ?? ???not supported, because silly!
----------------------------------------------??----------------------------------
^localpath(.*) /otherpath$1? ?? ?? ?? ?? ?? ?? ?/otherpath/pathinfo
??
^localpath(.*) /otherpath$1 [R]? ?? ?? ?? ?? ???
http://thishost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^localpath(.*) /otherpath$1 [P]? ?? ?? ?? ?? ???not supported, because silly!
----------------------------------------------??----------------------------------
^localpath(.*)
http://thishost/otherpath$1? ?? ?/otherpath/pathinfo
??
^localpath(.*)
http://thishost/otherpath$1 [R]??http://thishost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^localpath(.*)
http://thishost/otherpath$1 [P]??not supported, because silly!
----------------------------------------------??----------------------------------
^localpath(.*)
http://otherhost/otherpath$1? ???http://otherhost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
??
^localpath(.*)
http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via external redirection
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? (the [R] flag is redundant)
??
^localpath(.*)
http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? via internal proxy
??
舉例:

要重寫(xiě)這種形式的URL

/ Language /~ Realname /.../ File??



/u/ Username /.../ File . Language??

可以把這樣的對(duì)應(yīng)關(guān)系保存在/path/to/file/map.txt映射文件中, 此后,只要在Apache服務(wù)器配置文件中增加下列行,即可:

RewriteLog? ?/path/to/file/rewrite.log
RewriteMap? ?real-to-user? ?? ?? ?? ?? ?txt:/path/to/file/map.txt
RewriteRule??^/([^/]+)/~([^/]+)/(.*)$? ?/u/${real-to-user2|nobody}/$3.$1