重寫(xiě) Valve(Rewrite Valve) 實(shí)現(xiàn) URL 重寫(xiě)功能的方式非常類(lèi)似于 Apache HTTP Server 的 mod_rewrite 模塊。
重寫(xiě) Valve 是通過(guò)使用 org.apache.catalina.valves.rewrite.RewriteValve 類(lèi)名來(lái)配置成 Valve 的。
經(jīng)過(guò)配置,重寫(xiě) Valve 可以做為一個(gè) Valve 添加到 Host 中。參考虛擬服務(wù)器文檔來(lái)了解配置詳情。該 Valve 使用包含重寫(xiě)指令的 rewrite.config 文件,且必須放在 Host 配置文件夾中。
另外,重寫(xiě) valve 也可以用在 Web 應(yīng)用的 context.xml 中。該 Valve 使用包含重寫(xiě)指令的 rewrite.config 文件,且必須放在 Web 應(yīng)用的 WEB-INF 文件夾中。
rewrite.config 文件包含一系列指令,這些指令和 mod_rewrite 所用的指令很像,尤其是核心的 RewriteRule 與 RewriteCond 指令。
注意:該部分內(nèi)容修改自 mod_rewrite 文檔,后者版權(quán)歸屬于 Apache 軟件基金會(huì)(1995-2006),遵循 Apache 許可發(fā)布。
格式:RewriteCond TestString CondPattern
RewriteCond 指令定義了一個(gè)規(guī)則條件。一個(gè)或多個(gè) RewriteCond 指令可以?xún)?yōu)先于 RewriteRule 指令執(zhí)行。如果 URI 當(dāng)前狀態(tài)匹配它的模式,并且滿(mǎn)足了這些條件,才會(huì)使用下列規(guī)則。
TestString 是一種字符串,除了簡(jiǎn)單的文本之外,它還可以含有下列擴(kuò)展結(jié)構(gòu)。
HTTP\_USER\_AGENT
HTTP\_REFERER
HTTP\_COOKIE
HTTP\_FORWARDED
HTTP\_HOST
HTTP\_PROXY\_CONNECTION
HTTP\_ACCEPT
REMOTE\_ADDR
REMOTE\_HOST
REMOTE\_PORT
REMOTE\_USER
REMOTE\_IDENT
REQUEST\_METHOD
SCRIPT\_FILENAME
REQUEST\_PATH
CONTEXT\_PATH
SERVLET\_PATH
PATH\_INFO
QUERY\_STRING
AUTH\_TYPE
DOCUMENT\_ROOT
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
THE\_REQUEST
REQUEST\_URI
REQUEST\_FILENAME
HTTPS
這些變量對(duì)應(yīng)著相似名稱(chēng)的 HTTP MIME 報(bào)頭和 Servlet API 方法。多數(shù)都記錄在各種手冊(cè)和 CGI 規(guī)范中。下面列出了重寫(xiě) Valve 專(zhuān)有的那些變量:
另外還需要注意的是:
CondPattern 即條件模式,是一種應(yīng)用于 TestString 當(dāng)前實(shí)例的正則表達(dá)式。TestString 在匹配 CondPattern 之前,會(huì)首先求值。
謹(jǐn)記:CondPattern 是一種兼容 perl 并帶有一些擴(kuò)展的正則表達(dá)式。
注意:所有這些測(cè)試都可以加上前綴 ! 來(lái)使它們的含義反向。
ornext|OR(或者下一個(gè)條件)利用本地 OR(而不是隱式的 AND)來(lái)組合規(guī)則條件。典型范例為:
RewriteCond %{REMOTE_HOST} ^host1.* [OR]
RewriteCond %{REMOTE_HOST} ^host2.* [OR]
RewriteCond %{REMOTE_HOST} ^host3.*
RewriteRule ...some special stuff for any of these hosts...
沒(méi)有該標(biāo)記,你必須寫(xiě)三遍條件/規(guī)則對(duì)。
范例:
假如想根據(jù)請(qǐng)求頭的 User-Agent: 對(duì)網(wǎng)站主頁(yè)進(jìn)行重寫(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]
說(shuō)明:如果使用的瀏覽器將它自身標(biāo)識(shí)為 'Mozilla'(包括 Netscape Navigator、Mozilla,等等),那么這就是內(nèi)容最大化主頁(yè)(max homepage。它可以包含框架或其他特性);如果使用的是 Lynx 瀏覽器(基于終端的),那么獲得的就是內(nèi)容最小化的主頁(yè)(min homepage)——專(zhuān)為便于瀏覽文本而設(shè)計(jì)的版本;如果這些條件都不適用(你使用的是其他瀏覽器,或者你的瀏覽器將其自身標(biāo)識(shí)為非標(biāo)準(zhǔn)內(nèi)容),那么得到的就是標(biāo)準(zhǔn)主頁(yè)(std homepage)。
格式:RewriteMap name rewriteMapClassName optionalParameters。
通過(guò)用戶(hù)必須實(shí)現(xiàn)的一個(gè)接口來(lái)實(shí)現(xiàn)映射。類(lèi)名為 org.apache.catalina.valves.rewrite.RewriteMap,代碼為:
package org.apache.catalina.valves.rewrite;
public interface RewriteMap {public String setParameters(String params);public String lookup(String key);
}
格式:RewriteRule Pattern Substitution
RewriteRule 指令是重寫(xiě)機(jī)制的核心。此指令可以多次使用,每個(gè)實(shí)例都定義一個(gè)單獨(dú)的重寫(xiě)規(guī)則。這些規(guī)則的定義順序尤為重要,因?yàn)檫@是在運(yùn)行時(shí)應(yīng)用它們的順序。
模式是一個(gè)作用于當(dāng)前 URL 的兼容 perl 的正則表達(dá)式,這里的“當(dāng)前”是指該規(guī)則生效時(shí)的 URL,它可能與被請(qǐng)求的 URL 不同,因?yàn)槠渌?guī)則可能在此之前已經(jīng)發(fā)生匹配并對(duì)它做了改動(dòng)。
下面是關(guān)于正則表達(dá)式格式的一些提示:
文本:
量詞:
分組:(text)——文本分組(設(shè)定第 N 組可以被引用為 RewriteRule)
行錨
^——匹配一行起始處的空字符串。
$——匹配一行結(jié)束處的空字符串。
轉(zhuǎn)義
\char ——將指定字符轉(zhuǎn)義(比如將.、[]、() 等字符轉(zhuǎn)義)
要想了解更多關(guān)于正則表達(dá)式的信息,請(qǐng)參見(jiàn) perl 正則表達(dá)式在線(xiàn)聯(lián)機(jī)手冊(cè)(perldoc perlre)。關(guān)于正則表達(dá)式及其變體(POSIX 正則表達(dá)式)的詳情,可看看這本書(shū):
*Mastering Regular Expressions, 2nd Edition* (目前該書(shū)為第 3 版)
Jeffrey E.F. Friedl
O'Reilly & Associates, Inc. 2002
ISBN 978-0-596-00289-3
在規(guī)則中,NOT 字符(!)可作為模式的前綴,實(shí)現(xiàn)逆向模式。比如“如果當(dāng)前 URL 并不匹配該模式”。這可以用在易于匹配的是逆向模式這種異常情況下,或者也可以作為最后一個(gè)默認(rèn)規(guī)則來(lái)使用。
注意:在使用 NOT 字符反轉(zhuǎn)模式時(shí),不能在模式中包含分組的通配成分。這是因?yàn)椋绻J讲黄ヅ洌ū热绶雌ヅ洌?,分組內(nèi)將沒(méi)有內(nèi)容。如果使用了逆向模式,就不能在替代字符串中使用 $N。
重寫(xiě)規(guī)則中的替代字符串(substitution string)是一種用來(lái)取代模式匹配的原始 URL 的字符串。除了純文本之外,它還包括:
反向引用表示的是形式 $N(N 的范圍為 0-9),它是指用模式所匹配的第 N 組的內(nèi)容去替換 URL。服務(wù)器變量 RewriteCond 指令的 TestString 所用的相同。映射函數(shù)來(lái)自 RewriteMap 指令。這 3 類(lèi)變量都按照上述順序展開(kāi)。
如前所述,所有的重寫(xiě)規(guī)則都應(yīng)用于替代字符串(按照配置文件中所定義的順序)。URL 完全由替代字符串所替換,直到所有規(guī)則都應(yīng)用完畢,重寫(xiě)過(guò)程才結(jié)束(或利用 L 標(biāo)記來(lái)終止)。
還有一個(gè)特殊的替代字符串:-,意思是不替代,當(dāng)需要讓重寫(xiě)規(guī)則只匹配 URL 而不替換時(shí),就用得上它了。這一字符串通常與 C(chain)標(biāo)記配合使用,為的是在替換發(fā)生前應(yīng)用多個(gè)模式。
另外,還可以將 [flags] 做為 RewriteRule 的第三個(gè)參數(shù),從而為替代字符串設(shè)置特殊標(biāo)記。flags是一個(gè)包含下列標(biāo)記且標(biāo)記間以逗號(hào)分隔的列表:
此標(biāo)記使當(dāng)前規(guī)則與下一個(gè)規(guī)則(它又可以與其后規(guī)則相鏈接,如此反復(fù))相鏈接。 它產(chǎn)生如下效果:如果某個(gè)規(guī)則被匹配,通常會(huì)繼續(xù)處理其后繼規(guī)則,這個(gè)標(biāo)記就不起作用;如果某規(guī)則不被匹配,則其后繼鏈接規(guī)將會(huì)被忽略。比如,在執(zhí)行一個(gè)外部重定向時(shí), 對(duì)一個(gè)目錄級(jí)規(guī)則集,你可能需要?jiǎng)h除 .www(因?yàn)榇颂幉粦?yīng)該出現(xiàn) .www)。
在客戶(hù)端瀏覽器上設(shè)置一個(gè) cookie。cookie 的名稱(chēng)是 NAME,其值是 VAL。 domain 字段是該 cookie 的域,比如 .apache.org,可選的lifetime 是 cookie 生命周期(以分鐘計(jì)),可選的 path 是 cookie 的路徑。
強(qiáng)制一個(gè)名為 VAR 的請(qǐng)求變量值為 VAL,VAL可以包含可擴(kuò)展的反向引用的正則表達(dá)式 $N 和 %N??梢远啻问褂迷摌?biāo)記,以便設(shè)置多個(gè)變量。
強(qiáng)制禁止訪(fǎng)問(wèn)當(dāng)前的 URL——立即反饋一個(gè) HTTP 響應(yīng)代碼 403。使用這個(gè)標(biāo)記,可以鏈接若干 RewriteConds 以阻斷某些 URL。
強(qiáng)制當(dāng)前 URL 為已失效——立即反饋一個(gè) HTTP 響應(yīng)代碼 410(請(qǐng)求資源已被刪除)。使用這個(gè)標(biāo)記,可以標(biāo)明頁(yè)面已被刪除而不存在.
立即停止重寫(xiě)操作,并不再應(yīng)用其他重寫(xiě)規(guī)則。它對(duì)應(yīng)于 Perl 中的 last 命令或 C 語(yǔ)言中的 break 命令。使用該標(biāo)記可以防止當(dāng)前已被重寫(xiě)的 URL 被后續(xù)規(guī)則所繼續(xù)重寫(xiě)。比如,用它可以將根路徑的 URL(/)重寫(xiě)為實(shí)際存在的 URL,比如:/e/www/。
重新執(zhí)行重寫(xiě)操作(從第一個(gè)重寫(xiě)規(guī)則重新開(kāi)始)。這時(shí),要匹配的 URL 已不是原始 URL 了,而是經(jīng)最后一個(gè)重寫(xiě)規(guī)則處理過(guò)的 URL。它對(duì)應(yīng)于 Perl 中的 next 命令或 C 語(yǔ)言中的 continue 命令。此標(biāo)記可以重新開(kāi)始重寫(xiě)操作,立即回到循環(huán)的頭部。
但是要小心,不要制造死循環(huán)!
使模式不區(qū)分大小寫(xiě)。當(dāng)模式與當(dāng)前 URL 匹配時(shí),A-Z 和 a-z 沒(méi)有區(qū)別。
此標(biāo)記阻止重寫(xiě) Valve 對(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)化為 /bar?arg=P1=zed 的安全請(qǐng)求。
該標(biāo)記會(huì)強(qiáng)制重寫(xiě)引擎將替代字符串中的一個(gè)查詢(xún)字符串部分添加到已有字符串上,而不是簡(jiǎn)單地替換已有字符串。當(dāng)你想要通過(guò)重寫(xiě)規(guī)則為查詢(xún)字符串添加更多數(shù)據(jù)時(shí),可以使用該標(biāo)記。
將 http://thishost[:thisport]/(使新的 URL 成為一個(gè) URI)作為替代字符串的前綴,從而強(qiáng)制執(zhí)行一個(gè)外部重定向。如果沒(méi)有指定 code,則產(chǎn)生一個(gè)HTTP 響應(yīng)代碼 302(暫時(shí)移動(dòng))。如果需要使用在 300-400 范圍內(nèi)的其他響應(yīng)代碼,只需在此指定這個(gè)數(shù)值即可。另外,還可以使用下列符號(hào)名稱(chēng):temp(默認(rèn)),permanent、seeother。用它可以把規(guī)范化的 URL 反饋給客戶(hù)端,如重寫(xiě) /~ 為 /u/,或?qū)?u/user 加上斜杠,等等。
注意:在使用這個(gè)標(biāo)記時(shí),必須確保替換字段是一個(gè)有效的 URL!否則它會(huì)指向一個(gè)無(wú)效的位置!并且要記住,此標(biāo)記本身只是對(duì) URL 加上 http://thishost[:thisport]/ 前綴而已,不會(huì)妨礙重寫(xiě)操作。通常,你會(huì)希望停止重寫(xiě),然后立即重定向。要想停止重寫(xiě),你還需要添加 L 標(biāo)記。
如果當(dāng)前規(guī)則匹配,此標(biāo)記會(huì)強(qiáng)制重寫(xiě)引擎跳過(guò)當(dāng)前匹配規(guī)則后面的 num 個(gè)規(guī)則。它可以實(shí)現(xiàn)一個(gè)類(lèi)似 if-then-else 的構(gòu)造:then 子句的最后一個(gè)規(guī)則是 skip = N,其中 N 代表 else 子句中的規(guī)則數(shù)目。(該標(biāo)記不同于chain|C 標(biāo)記?。?/span>
強(qiáng)制指定目標(biāo)文件的 MIME 類(lèi)型為 MIME-type,可基于一些條件設(shè)置內(nèi)容類(lèi)型。比如在下面的代碼段中,如果利用 .phps 擴(kuò)展調(diào)用 .php 文件,它們就能被 mod_php 模塊顯示。
RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]