ISAPI Filter編程重寫URL

問題描述:要在一個Web站點上實現二級域名Url的重寫。例如:http://abc.company.com/ 重寫到 http://company.com/usersite.asp?sitename=abc 其中abc二級域名不定,根據用戶申請的名字來決定。服務器上有一個DNS服務。可以吧*.compay.com所有二級域名正確解析到company.com。經過重寫後。瀏覽器中的地址是http://abc.company.com/ 但實際請求的地址是 http://company.com/usersite.asp?sitename=abc 讓用戶感覺好像在訪問 http://abc.company.com/

好像在Apache上用Apache的mod_rewrite,配置一下就可以輕鬆的解決問題了。據說微軟的IIS7中也支持了這種特性,IIS7可以在 IIS 請求管道的任何地方執行一個HttpModule,下面是IIS7給的配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration> <configSections>
<section name="rewriter"
requirePermission="false"
type="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter" />
</configSections>
<system.web>
<httpModules>
<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter" />
</httpModules>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
<rewriter>
<rewrite url="~/products/(.+)" to="~/products.aspx?category=$1" />
</rewriter>
</configuration>


遺憾的是服務器使用的是Win2003+IIS6。並且服務器上同時部署了asp程序和asp.net程序如果使用 UrlRewriter.net組件,只能在HttpModule一級重寫,只能作用於所有使用 % WINDIR %/Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll處理請求的後綴文件。如 .aspx .ascx請求。但是asp是用%WINDIR%/WINDOWS/system32/inetsrv/asp.dll來處理請求的。請求不會分檢到Asp.net的HttpModule中。所以對於asp的請求,UrlRewriter.net組件的HttpModule重寫不能起效。.jpg .gif .htm也不能被重寫。看來只能用ISAPI Filters http://msdn2.microsoft.com/en-us/library/ms525908.aspx 來重寫了。

SAPI Filters有兩個非常著名工程:
1. Helicon Techs ISAPI Rewrite: http://www.isapirewrite.com/ 提供一個99美元(可免費試用30天)的ISAPI URL重寫產品完整版,以及一個免費的輕量級版本。
2. Ionics ISAPI Rewrite: http://cheeso.members.winisp.net/IIRF.aspx 全免費開源組件。

Helicon Techs ISAPI Rewrite的產品完整版已經解決了這個問題。可是Helicon Techs的付費手段少,在付費線購買太難用了,如果像支付寶一樣好用(點擊付款連再次確認都沒有,直接錢就出去了 呵呵)估計會增加購買量。

看來自己動手豐衣足食的時候到了,從Ionics ISAPI Rewrite的基礎上改一個可以支持二級域名重寫的ISAPI Filter吧。下載Ionics Isapi Rewrite Filter(下面簡寫爲IIRF) http://www.codeplex.com/IIRF/Release/ProjectReleases.aspx?ReleaseId=5018 。最後一個版本是1.2.12c Beta 千萬不要用1.2.12b,1.2.12b有內存泄露問題。1.2.12c修復了這個問題(加了free( myCopy )部分的代碼)。

下載後主要有8 個文件。IsapiRewrite4.c TestDriver.c IirfConfig.h IirfConstants.h IirfRequestContext.h RewriteRule.h pcre-5.0/ pcre.h pcre-5.0/pcre.lib 其中的TestDriver.c是測試正則表達式的exe可以先不看。RewriteRule.h pcre-5.0/ pcre.h pcre-5.0/pcre.lib 是正則表達式解析引擎。

修改makefile中:VC="C:/Program Files/Microsoft Visual Studio 8/VC" 和PCRESOURCE=E:/Project/InUrlRewrite/SRC/pcre-5.0 部分。到.net 2.0的console下cd進入下載目錄使用 nmake –f makefile編譯。讓工程可以正確編譯。

搭建一個可以測試自己編譯的ISAPI Filter的環境。建一個WebSite在ISAPI Filters添加剛剛Build好的IsapiRewrite4.dll。重啓IIS。在IsapiRewrite4.ini中設置輸出Log等級爲5(輸出詳細Log)指定Log輸出位置。修改%WINDIR%/system32/drivers/etc/hosts文件。在域名解析中加入127.0.0.1 abc.company.com 和 127.0.0.1 company.com這兩行便於測試。在新建的WebSite中加入一個test.asp文件,test.asp中只用寫Response.Write(Query("Domain")) 提供重寫後的測試。

到這裏所有的編程前需要的環境都部署好了。現在可以開始改 IIFR了。看完了所有的代碼,發現核心的內容都在IsapiRewrite4.c中,這個文件總共有2600多行。核心的函數是DoRewrites。對外的Entry-Point Functions是GetFilterVersion HttpFilterProc TerminateFilter通過這三個方法向IIS暴露 ISAPI Filter內部的功能,IIS會調用ISAPFilter的這三個方法。在http://msdn2.microsoft.com/en-us/library/ms525572.aspx 中有詳細的介紹。

主要修改DoRewrites就基本上可以滿足要求了。
1. 添加一個新的表示Pattern -> [D]。
2. 修改ApplyRules方法對Url的處理,當表示Pattern是[D]時,從GetServerVariable("HTTP_HOST", pfc)中取得http_host,拼湊到OriginalUrl前再進行正則表達式的匹配。
經過上面兩部就實現了對二級域名重寫的功能。

注意:IIFR的License要求(在IsapiRewrite4.c頂部有詳細的描述)很嚴格。可能不允許再生產,和商業使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章