Apache mod_rewrite 筆記

官網的說明在此:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html

mod_rewrite對我來說算是常用的一個功能, 但是網路上很少找到完整的教學. 所以就只好自己看官網的文件邊啃邊測試了.

注意事項:

  1. 要使用 mod_rewrite 的虛擬主機或資料夾, 必須設定 Options FollowSymLinks, 否則無法運作.
  2. Pattern 比對的可能是 URL, 也可能是檔案路徑, 這要看我們在何處使用 RewriteRule. 差別在於 URL 開頭會有斜線, 路徑不會, 因此在寫 Pattern 時要注意.
  3. 有可能形成無限迴圈. 這會嚴重影響效能. 在新版 Apache 若改寫前後的檔案相同, 會自動停止.

設定紀錄檔:

在 httpd.conf 中加入以上設定, 就可以開啟 log 功能. log 等級從 1 到 9, 數字越大越詳細. 開發或除錯時可以很方便的瞭解實際的運作情形. 我們可以給每個虛擬主機設定不同的紀錄檔, 但無法給資料夾設定紀錄檔. 例如以下這段設定, 上面的可以執行, 下面的則會出現錯誤訊息

錯誤訊息會抱怨說 RewriteLog 這個設定不能使用在這邊

基本語法:

這個設定就是 mod_rewrite 真正在做事情的地方了, Pattern 是用來比對我們想要改寫的原始內容, Substitution 則是我們要將其改寫成什麼樣子. 換句話說, 只有符合 Pattern 的情況下才會進行改寫的動作. flags 可以設定一些選項, 例如說不想區分大小寫, 就可以使用 [NC] 這個 flag.

在一般情況下, RewriteRule 是照順序一個一個執行下去的, 且前面一條改寫過的輸出會成為下一條的輸入, 所以安排好合理的順序會是很重要的關鍵. 下面的例子, 首先 about.htm 符合 Pattern, 變成 about1.php, 然後執行下一條規則, about1.php 又符合 Pattern, 所以最後會跑去 about2.php

兩種情境:

當使用在 VirtualHost 標籤中, 或是不在任何標籤中, 將會以 Host 情境執行. 在這個情況下, 拿來與 Pattern 比對的是 URL, 包含開頭的斜線. 反之, 若我們是在 Directory 或是 htaccess 檔案中使用, 則會以 per-directory 情境執行, 這時會用檔案路徑去與 Pattern 比對. 例如我們分別用上面的設定來執行以下例子, 會發現在 log 中它是用不同的字串去與 Pattern 比對:

Pattern 的用法:

Pattern 的部份是使用正則表達式(Regular Expression), 在大部分常見的用途當中, 其實並不會用到太複雜的語法. 然而它畢竟是個威力強大的表示方法, 一有不小心就可能產生預期之外的結果, 例如:

注意這個例子前後 url 的變化, 路徑不見了, 只剩下檔名. 這是因為 Pattern 給的不夠精確, 造成我們不管存取任何路徑的 about.htm, 都會符合 Pattern. 而改寫時, Substitution 又不包含路徑, 所以路徑也就自然不見了.

單一入口頁面:

另外, 一個經典的使用方法, 是將所有的網頁請求交給單一頁面處理, 例如:

但這邊用來判定檔案是否存在的方法需要注意, 若是在VirtualHost中使用, %{REQUEST_FILENAME}得到的是 /something.php 這樣的路徑, 於是rewrite會去檢查系統根目錄底下的something.php, 而不是網頁根目錄底下的檔案, 這會造成功能不正常, 可以說完全無法使用.
解決辦法, 就是加上<Location />, 並在其中設置rewrite的語法:

強制使用 https :

如果想要將整個網站改成使用 https, 這是其中一種方法

發佈留言