<-
Apache > HTTP 伺服器 > 文件 > 2.4 版 > 重寫規則

進階技術 mod_rewrite

可用語言:  en  |  fr 

這份文件補充了 mod_rewrite 參考文件。它提供了一些 mod_rewrite 的進階技術。

請注意,這些範例中有很多在您的特定伺服器組態中可能無法直接使用,所以重要的是您要瞭解這些範例,而不是直接複製貼上到您的組態中。
Support Apache!

另請參閱

top

根據 URL 對多個後端進行分片

說明

分散伺服器負載或儲存空間負擔的一種常見技術稱為「分片」。使用此方法時,前端伺服器會使用 url,將使用者或物件分配到後端伺服器上,以達成「分片」的效果。

解決方案

使用者對應目標伺服器的對應表,會記錄在外接對應檔案中。它們看起來像這樣

user1 user1 的實體主機
user2 user2 的實體主機
# ... 等等

我們可以將它放入一個 map.users-to-hosts 檔案中。目的是對應;

/u/user1/anypath

http://user1 的實體主機/u/user/anypath

因此,每個 URL 路徑不一定要在每個後端實體主機上都是有效的。在對應檔案的協助下,以下的規則集就能發揮這個作用,假設 server0 是預設的伺服器,它會在使用者在對應表中沒有資料時使用

RewriteEngine on
RewriteMap    users-to-hosts      "txt:/path/to/map.users-to-hosts"
RewriteRule   "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"

有關這個指令語法的詳細說明,請參閱 RewriteMap 文件和 RewriteMap 操作教學

top

即時產生內容

說明

我們希望動態產生內容,但在產生後一次儲存為靜態內容。這個規則會檢查靜態檔案的存在,如果不存在,會產生靜態檔案。如有需要,可以定期移除靜態檔案(如透過 cron),並會依需要重新產生。

解決方案
這是透過下列規則集完成
# This example is valid in per-directory context only
RewriteCond "%{REQUEST_URI}"   "!-U"
RewriteRule "^(.+)\.html$"     "/regenerate_page.cgi"   [PT,L]

-U 運算子會判斷測試字串(本例中為 `REQUEST_URI`)是不是有效的網址。透過次請求完成這動作。如果次請求失敗,也就是所要求的資源不存在,這個規則會呼叫 CGI 程式碼 `regenerate_page.cgi`,產生要求的資源並將其儲存於文件目錄,以便下次要求時可以提供靜態副本。

這樣一來可以以靜態形式提供不常更新的文件。如果需要更新文件,可以從文件目錄中刪除,然後在下次要求時會重新產生。

top

負載平衡

說明

我們希望使用 mod_rewrite 隨機將負載分配到多個伺服器。

解決方案

我們會使用 RewriteMap 和一份伺服器清單完成這動作。

RewriteEngine on
RewriteMap lb        "rnd:/path/to/serverlist.txt"
RewriteRule "^/(.*)" "http://${lb:servers}/$1"     [P,L]

serverlist.txt 會包含伺服器清單

## serverlist.txt

servers one.example.com|two.example.com|three.example.com

如果您希望其中一個特定的伺服器取得多於其他伺服器的負載,請將其加入更多次至清單中。

討論

Apache 內建一個負載平衡模組 - mod_proxy_balancer,它的彈性以及功能比您用 mod_rewrite 拼湊起來的要好太多了。

top

結構化使用者目錄

說明

某些擁有數千名使用者的網站會使用結構化的主目錄佈局,也就是每個主目錄都位於一個子目錄中,其開頭(例如)是使用者名稱的第一個字元。因此,/~larry/anypath/home/l/larry/public_html/anypath ,而 /~waldo/anypath/home/w/waldo/public_html/anypath

解決方案

我們使用下列規則集將主目錄 URL 擴充到以上的佈局。

RewriteEngine on
RewriteRule   "^/~(([a-z])[a-z0-9]+)(.*)"  "/home/$2/$1/public_html$3"
top

重新導向錨點

說明

預設情形下,重新導向到 HTML 錨點會失敗,因為 mod_rewrite 會將 # 字元轉譯成 %23,而這會中斷重新導向。

解決方案

RewriteRule 中使用 [NE] 旗標。NE 代表 No Escape(不轉譯)。

討論
當然,這種技術也可以使用在其他 mod_rewrite 預設進行 URL 編碼的其他特殊字元。
top

與時間相關的重寫

說明

我們希望使用 mod_rewrite 依時間提供不同的內容。

解決方案

有很多 TIME_xxx 變數可用於重寫條件。搭配特殊的字典比對模式 <STRING>STRING=STRING,我們可以執行與時間相關的重新導向

RewriteEngine on
RewriteCond   "%{TIME_HOUR}%{TIME_MIN}" ">0700"
RewriteCond   "%{TIME_HOUR}%{TIME_MIN}" "<1900"
RewriteRule   "^foo\.html$"             "foo.day.html" [L]
RewriteRule   "^foo\.html$"             "foo.night.html"

這項措施提供 foo.day.html 的內容在 07:01-18:59 之間於 URL foo.html 中顯示,而其餘時間則顯示 foo.night.html 的內容。

mod_cache、中間代理伺服器和瀏覽器各會快取回應,並且可能導致任一頁面在已設定的時間區段外顯示。您可以使用 mod_expires 來控制此效果。您當然可以選擇單純以動態方式提供內容,並根據時間客製化內容。
top

依循 URL 區段設定環境變數

說明

有時候,我們希望在執行重新導向時維持某種類型的狀態。例如,您希望註記該重新導向已執行,以便稍後檢查要求是否透過重新導向取得。設定環境變數是一種執行此動作的方法。

解決方案

使用 [E] 旗標設定環境變數。

RewriteEngine on
RewriteRule   "^/horse/(.*)"   "/pony/$1" [E=rewritten:1]

稍後在規則集中,您可以使用 RewriteCond 檢查這個環境變數。

RewriteCond "%{ENV:rewritten}" "=1"

請注意,環境變數在外部重新導向時無法維持。您可能會考慮使用 [CO] 旗標來設定 cookie。對於每目錄與 htaccess 重新導向(其中最終替換會當作內部重新導向來處理),前一輪重新導向的環境變數會加上 "REDIRECT_" 前綴。

可用語言:  en  |  fr 

top

留言

注意事項
這裡不是問答區。放在這裡的留言應提出關於改善文件內容或伺服器的建議,如果這些建議已被實作或是被視為無效/離題,可能會被我們的管理員移除。關於如何管理 Apache HTTP Server 的問題應導向 Libera.chat 上的 IRC 頻道 #httpd,或寄送至我們的 郵件列表