Apache HTTP 伺服器版本 2.4
此文件補充 mod_rewrite
參考文件。它說明使用 mod_rewrite
所需的基本概念。其他文件會深入說明,但此文件應有助初學者入門。
Apache 模組 mod_rewrite
是一個非常強大且複雜的模組,提供了執行網址操作的方法。使用它,您可以執行幾乎所有您需要的網址改寫。然而,它有點複雜,初學者可能會感到害怕。此外,也常將改寫規則視為一種魔法咒語,在不了解其作用的情況下使用它們。
本文檔嘗試提供充分的背景說明,讓後續內容易於理解,不會只是盲目複製。
請記住,許多常見的網址操作工作並不需要 mod_rewrite
的所有功能和複雜性。對於簡單的工作,請參閱 mod_alias
和關於 將網址對應到檔案系統 的文件。
最後,在繼續後續操作之前,請務必使用 LogLevel
指令將 mod_rewrite
的日誌層級設定為其中一個追蹤層級。雖然這可能會提供大量的資訊,但它對於偵錯 mod_rewrite
設定的問題是不可或缺的,因為它會告訴您每個規則是如何處理的。
mod_rewrite
使用 Perl 相容正規表示法 語彙。
在此文件中,我們不提供正規表示法的詳細參考。對於細節,我們推薦 PCRE 手冊頁面、Perl 正規表示法手冊頁面,以及 Jeffrey Friedl 撰寫的 Mastering Regular Expressions。
在此文件中,我們提供足夠的 regex 語彙,讓您快速上手,而不會不知所措,希望 RewriteRule
s 具有科學公式,而不是魔咒咒語。
以下是撰寫正規表示法和 RewriteRule
所需的基本構件。它們肯定無法表示完整的正規表示法語彙,但這是個起點,應該能幫助您閱讀基本正規表示法,以及撰寫您自己的正規表示法。
字元 | 意義 | 範例 |
---|---|---|
. |
與任何單一字元相符 | c.t 將與 cat 、cot 、cut 等相符 |
+ |
重複前一次相符項一次或多次 | a+ 與 a 、aa 、aaa 等相符 |
* |
重複前一次相符項零次或多次 | a* 與 a+ 相符項相同,但也會與空字串相符 |
? |
使相符項為選擇性 | colou?r 將與 color 和 colour 相符 |
\ |
轉譯下一個字元 | \. 將與 . (點)相符,而不是如上說明的 任何單一字元 |
^ |
稱為錨點,與字串開頭相符 | ^a 與以 a 開頭的字串相符 |
$ |
另一個錨點,與字串結尾相符 | a$ 與以 a 結尾的字串相符 |
( ) |
將多個字元分組為單一單位,並捕獲相符項以供反向參照使用 | (ab)+ 與 ababab 相符 - 也就是說,+ 適用於群組。有關反向參照的詳細資訊,請參閱 以下內容 |
[ ] |
一個字元類別 - 與其中一個字元相符 | c[uoa]t 與 cut 、cot 或 cat 相符 |
[^ ] |
負向字元類別 - 與未指定的任何字元相符 | c[^/]t 與 cat 或 c=t 相符,但與 c/t 不相符 |
在 mod_rewrite
中,!
字元可以用於正規表示法之前,以否定它。也就是說,當且僅當字串與表示法的其他部分不相符時,才視為已相符。
這裏有一件重要的事必須記住:無論你什麼時候在 Pattern 或是 CondPattern 中使用括號,系統都會建立內部的反向參照,可用於字串 $N
和 %N
(見下文)。這些可供建立 RewriteRule
的 Substitution 參數或是 RewriteCond
的 TestString 參數。
RewriteRule
模式中的捕獲(反直覺地)可用於所有前置的 RewriteCond
指令,因為 RewriteRule
表達式在個條件之前評估。
圖 1 呈現了反向參照展開的位置以及說明 RewriteRule、RewriteCond 配對的流程。在接下來的章節中,我們將探索如何使用這些反向參照,所以如果你一開始有點陌生,不用煩惱。
圖 1: 反向參照經由規則擴充。
在這個範例中,對 /test/1234
的請求會轉換成 /admin.foo?page=test&id=1234&host=admin.example.com
。
RewriteRule
包含三個參數,以空格分隔。這些參數是
Pattern 是 正規表示法。最初(針對第一條改寫規則或在替換發生之前)與輸入請求的 URL 路徑配對(主機名稱之後且在疑問號之前標示查詢字串開始的任何部分),或在每個目錄的脈絡下與請求相對於規則所定義的目錄的路徑進行配對。一旦替換發生,後續規則將與替換值配對。
圖 2: RewriteRule 指令的語法。
Substitution 本身可以是三件事中的其中一件事
RewriteRule "^/games" "/usr/local/games/web/puzzles.html"
這會將請求對應到檔案系統上的任意位置,很像 Alias
指令。
RewriteRule "^/games$" "/puzzles.html"
如果 DocumentRoot
設定為 /usr/local/apache2/htdocs
,那麼這個指令將對 http://example.com/games
的請求對應到路徑 /usr/local/apache2/htdocs/puzzles.html
。
RewriteRule "^/product/view$" "http://site2.example.com/seeproduct.html" [R]
這告訴客戶端建立指定 URL 的新請求。
/usr/
)存在於檔案系統中,而 2 則不存在。(即檔案系統中沒有 /bar/
作為根目錄。)Substitution
也可包含往後參照的 Pattern 匹配的,來自於輸入 URL 路徑的部份。考慮下列範例
RewriteRule "^/product/(.*)/view$" "/var/web/productdb/$1"
變數 $1
會替換掉 Pattern 中括弧內表達式所匹配的文字。例如,針對 http://example.com/product/r14df/view
的請求會對應到路徑 /var/web/productdb/r14df
。
若括弧裡有以上一個以上的表達式,它們會依序在變數 $1
、$2
、$3
等中使用。
的行為會隨著規則最後的其中一個或多個旗標應用而被修改。例如,規則的配對行為可透過應用 RewriteRule
[NC]
記號來調整大小寫不敏感
RewriteRule "^puppy.html" "smalldog.html" [NC]
有關可用旗標、其意義和範例的更多詳細資訊,請參閱 重寫旗標 文件。
一個或多個
指示條件可被用來限制類型的請求,而接下來的 RewriteCond
會針對這些請求進行判斷。第一個參數是一個描述請求特性的變數,第二個參數是一個必須與該變數配對的 正規表示法,第三個可選參數是一個旗標清單,用來修改匹配的評估方式。RewriteRule
圖 3: RewriteCond 指示條件的語法
例如,若要將來自特定 IP 範圍的所有請求都導向到另一部伺服器,可以使用
RewriteCond "%{REMOTE_ADDR}" "^10\.2\." RewriteRule "(.*)" "http://intranet.example.com$1"
若指定了一個以上的
,則在套用 RewriteCond
之前,必須全部與之匹配。例如,若要拒絕查詢字串中包含「hack」字樣的請求,除非其也包含一個含有「go」字樣的 Cookie,可以使用RewriteRule
RewriteCond "%{QUERY_STRING}" "hack" RewriteCond "%{HTTP_COOKIE}" !go RewriteRule "." "-" [F]
請注意,感嘆號指定一個否定匹配,因此僅在 Cookie 不包含「go」的情況下,才會套用這個規則。
包含在
中的正規表示法中找到的匹配,可用於 RewriteCond
中 RewriteRule
Substitution
的一部份,使用變數 %1
、%2
等等。例如,這個範例會根據用來存取網站的主機名稱將請求導向不同的目錄
RewriteCond "%{HTTP_HOST}" "(.*)" RewriteRule "^/(.*)" "/sites/%1/$1"
如果請求是 http://example.com/foo/bar
,那麼 %1
會包含 example.com
,$1
會包含 foo/bar
。
RewriteMap
指令提供了一個呼叫外部函式的途徑,也就是為你改寫你的重寫。這將在 RewriteMap 補充說明 中進行更詳細的討論。
重寫通常在主伺服器組態設定 (在任何 <Directory>
區段之外) 或在 <VirtualHost>
容器中組態。這是執行重寫最簡單的方式,建議使用此方式。然而,在 <Directory>
區段或 .htaccess
檔案 中執行重寫也是可能的,但會帶來一些額外的複雜性。此技術稱為目錄重寫。
與伺服器重寫的主要差異在於,在 RewriteRule
中進行比對之前,包含 .htaccess
檔案的目錄路徑前綴會被移除。此外,應使用 RewriteBase
來確保請求正確對應到映射。