怎麼玩 URL Rewriting

URL Rewriting,這個好像似曾相識,又覺得很陌生的技術,已經隨著資訊安全與 SEO (Search Engine Optimization) 的腳步,逐漸影響每個 Web Developer,不論你是走哪個技術的(ASP, ASP.NET, PHP, JSP, Ruby, Perl, ...),基本上都很難不去重視它,因為它其實可以幫你很多忙。光是一個 REST 的 URL 樣式,就可以讓很多人眼睛為之一亮。

URL Rewriting,這個好像似曾相識,又覺得很陌生的技術,已經隨著資訊安全與 SEO (Search Engine Optimization) 的腳步,逐漸影響每個 Web Developer,不論你是走哪個技術的,基本上都很難不去重視它,因為它其實可以幫你很多忙。光是一個 REST 的 URL 樣式,就可以讓很多人眼睛為之一亮。

試想,如果你的網站有某支 URL 是長這樣好看:
http://www.abc.com.tw/myblog/blog.aspx?id=18472938290&postdate=20090404

還是這樣好看:
http://www.abc.com.tw/myblog/2009/04/04/18472938290.aspx

又或者,使用者是否可以用這樣的輸入 URL 方式:
http://www.abc.com.tw/productinfo/MP3

去列出他想要搜尋的 MP3 Player 的型錄,還是要使用者去打:
http://www.abc.com.tw/productinfo/search.aspx?keyword=MP3 這樣的 URL?

我想對行銷或消費者行為有概念的人來看的話,答案就很明顯了。

URL Rewriting 的強項,就是將外表的 URL,轉換成內部自己看的到的 URL 再做處理,可以讓內部的 URL 繼續使用,又可以讓外部的 URL 具親和性,因此 URL Rewriting 現在已經逐漸成為網站開發人員必須要知道的技術之一,而且現在其實已經有很多 URL Rewriting 的模組可以使用了,例如 UrlRewriting.Net 這個套件,或是 IIS 7.0 中的 URL Rewriting Module 等。

不過,如果能夠自己走一遭的話,會更了解 URL Rewriting 是什麼,而且對於網路上的 URL Rewriting 模組,也會更具精確的掌握力(以下以 ASP.NET 為主要說明的技術,其他的語言請參照手冊,找出相對應的功能)。

首先,URL Rewriting 是作為外部與內部 URL 要求的轉換器,它需要過濾所有的 URL,來執行重轉向的動作,因此它比較適合生存在 Web Server 的執行過程中,以 ASP.NET 來說,使用 HTTP Module 即可處理這方面的工作(HTTP Handler 較不適合)。

接者,設定處理 HttpApplication.BeginRequest 或是 HttpApplication.AuthorizeRequest 事件(多數的模組都是處理 HttpApplication.AuthorizeRequest 事件):

public void Init(HttpApplication context)
{
    context.AuthorizeRequest += new EventHandler(AppAuthorizeRequest);
}

然後再於事件常式中,呼叫 HttpApplication.Context.RewritePath() 即可:

public void AppAuthorizeRequest(object sender, EventArgs e)
{
    (sender as HttpApplication).Context.RewritePath("~/MyHandler.aspx");
}

然後,在 Web.config 中,將這個模組掛到 system.web/httpModules 設定中,若是 IIS 7.0,則要設在 system.webServer/modules 中。

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
        <add name="UrlRewritingHandler" type="UrlRewritingModule" />
    </modules>
</system.webServer>

然後執行這個 Web Application,不論你輸入哪個 URL 路徑,都會被導向到 MyHandler.aspx 中(當然,你的專案中要有 MyHandler.aspx 這個網頁)。

URL Rewriting 其實技術上就是這樣而已,透過 HttpApplication.Context.RewritePath() 將要求的 URL 傳到指定的網頁來處理,然而在開發實務上,URL Rewriting 要考量的其實很多:

  1. 由於每個 URL 都會被處理,那如果 URL 指向的是圖片,檔案,scripts 或其他資源時要如何處理?
  2. 是否有特殊要排除的路徑?
  3. 執行 URL Rewriting 時,URL 的格式要怎麼設計才會符合需求?
  4. 由於 URL 被重寫時,<form> 的 action 屬性會反應內部的 URL,而不是外部的 URL,此時要如何處理?
  5. URL Rewriting 對效能很要求,因為它要處理每一個 URL 要求,而不是選擇性不處理。

另外,URL 也不是一定要硬性的做 Rewriting,部份需要排除的就不需要做 Rewriting,或者你有某種格式的 URL 是要做重導向 (HTTP 302) 的話,也可以直接輸出 HTTP 302 訊息要求瀏覽器重導向即可,切記,不要在 URL Rewriting 中加太多的判斷條件,也不要在 URL Rewriting 中做太耗時間的事,那只會拖慢 URL 的處理速度(例如還要連資料庫存取資料這種事)。