Apache服務(wù)器 Apache服務(wù)器原生支持了URL-Rewrite。在config中打開LoadModule rewrite_module modules/
mod_rewrite.so 然后配置重寫的
正則表達(dá)式。例如:
摘引自Apache2.2中文參考手冊 中文手冊 Apache-UrlRewrite
--------------------------------------------- |
這個規(guī)則的目的是強制使用特定的主機(jī)名以代替其他名字。比如,你想強制使用www.example.com代替example.com,就可以在以下方案的基礎(chǔ)上進(jìn)行修改: |
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] |
RewriteCond %{HTTP_HOST} !^$ |
RewriteCond %{SERVER_PORT} !^80$ |
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] |
RewriteCond %{HTTP_HOST} !^$ |
--------------------------------------------------------------------------- |
IIS6/IIS7 Web服務(wù)器
IIS7新的“管道模式”其實是把ASP.NET中的某些概念與IIS進(jìn)行了更加深度的集成。在IIS7 Program Manager: Mike Volodarsky的Blog中有一篇文章分析了這方面的內(nèi)容:
Breaking Changes for ASP.NET 2.0 applications running in Integrated mode on IIS 7.0
IIS7的“經(jīng)典模式”與IIS 6基本上是如出一轍的。
在IIS6 + Asp.Net應(yīng)用程序級的URL-Rewrite,只能在請求被分配到Asp.Net引擎后才能發(fā)生重寫操作。在IIS7這一點被改變了。IIS7可以對沒有后綴名的請求進(jìn)行重寫,Asp.Net和IIS7進(jìn)行了深度的集成。IIS7可以在 IIS 請求管道的任何地方執(zhí)行一個HttpModule,下面是一個IIS7下Asp.Net的重寫配置:
摘引自ScottGu的Blog
<?xml version= "1.0" encoding= "UTF-8" ?> |
requirePermission= "false" |
type= "Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter" /> |
<add name= "UrlRewriter" type= "Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter" /> |
<modules runAllManagedModulesForAllRequests= "true" > |
<add name= "UrlRewriter" type= "Intelligencia.UrlRewriter.RewriterHttpModule" /> |
<validation validateIntegratedModeConfiguration= "false" /> |
<rewrite url= "~/products/(.+)" to= "~/products.aspx?category=$1" /> |
其中:<rewrite url="~/products/(.+)" to="~/products.aspx?category=$1" />這條規(guī)則中的~/products/(.+)這條正則表達(dá)式。匹配了/products/下的所有鏈接。
IIS6服務(wù)器級別下的重寫需要使用ISAPI Filters Rewrite來實現(xiàn)。
ISAPI Filters有兩個非常著名工程:
1)Helicon Techs ISAPI Rewrite: http://www.isapirewrite.com/ 提供一個99美元(可免費試用30天)的ISAPI URL重寫產(chǎn)品完整版,以及一個免費的輕量級版本。
2)Ionics ISAPI Rewrite: http://cheeso.members.winisp.net/IIRF.aspx 全免費開源組件。
在 ISAPI Filter編程重寫URL 中有說明。
服務(wù)器級的重寫與應(yīng)用程序級的重寫最大的區(qū)別在于他們發(fā)生的時機(jī)不同。下圖是在服務(wù)器級把/Pd/Book.aspx重寫到/Pd.aspx?Cg=books
請求還沒有到Asp.Net引擎,就被重寫了。
3.Asp.Net級別上重寫的一些小細(xì)節(jié)問題(部分內(nèi)容源自ScottGu 的Blog)
如果頁面中存在form且form是runat=server的<form runat="server">,那么這個頁面在重寫后form的action是原始URL,不是重寫后干凈的URL。例如/Pd/Book.aspx重寫到/Pd.aspx?Cg=books這個場景。實際用戶瀏覽器訪問的地址是/Pd/Book.aspx,在服務(wù)器級被重寫后請求變成了/Pd.aspx?Cg=books,在這種情況下form的action會被render成/Pd.aspx?Cg=books,其實這時更加想要action被render成/Pd/Book.aspx,讓頁面PostBack到同一位置。在某些情況下action被render成/Pd.aspx?Cg=books是不會對正常工作有影響的,只要/Pd.aspx?Cg=books不被重寫規(guī)則匹配上,/Pd.aspx?Cg=books會被正確發(fā)回到Asp.Net引擎。但是瀏覽器上的地址欄會變化,暴露出真正的地址。如果這個URL被某個別的規(guī)則匹配,那就必須要求form的action被正確的Render成/Pd/Book.aspx,這種統(tǒng)一的重寫后的URL。
解決辦法:
1)自己包裝form控件。把url寫在某個hidden field里同postback一起回來,render時修改action為hidden field里的url.
2)使用JavaScript在form submit前修改action例如 window.document.forms[0].action = window.location;
3)使用ASP.NET 2.0 Control Adapter(源自ScottGu 的Blog)
這種重寫是當(dāng)在使用Asp.Net應(yīng)用程序一級的重寫時,使用Context.Request.RawUrl填寫form的action,當(dāng)使用IIS應(yīng)用服務(wù)器一級的重寫時把干凈的URL記錄在Request.ServerVariables["HTTP_X_REWRITE_URL"]中,使用Request.ServerVariables["HTTP_X_REWRITE_URL"]填寫form的action,填寫form action 的過程都是通過Control Adapter對form Control擴(kuò)展,override form控件的 WriteAttribute方法,在Render時重新指定form的action。
核心源代碼 摘引自ScottGu的Blog
重寫后路徑兼容問題
在/Pd/Book.aspx重寫到/Pd.aspx?Cg=books的場景中,頁面中如果有相對位置的資源,如某個img的src=”../logo.gif”或src=”logo.gif”。這時瀏覽器請求這些資源基準(zhǔn)的位置是/pd/也就是說src=”../logo.gif”請求的路徑是/logo.gif,src=”logo.gif”請求的路徑是/pd/logo.gif。但是其實這些資源的基準(zhǔn)位置是 / 因為原始的URL是/Pd.aspx?Cg=books。這時就會發(fā)生資源找不到的情況。
1)使用服務(wù)器端的img使用 ~ 路徑可以解決這個問題(源自ScottGu的Blog)。
2)使用<base href=" http://xxx/ "></base>標(biāo)簽,這個標(biāo)簽需要寫在head里。告訴頁面,頁面中所有相對路徑的基準(zhǔn)路徑是 http://xxx/ ,從而解決重寫后路徑失效的問題。
base標(biāo)簽的說明: http://www.w3school.com.cn/tags/tag_base.asp
到這里,URL-Rewrite的問題討論完了。在實際項目中肯定還會遇到各種不同的問題,不過解決的思路,估計會是上面這些技術(shù)的組合和擴(kuò)展,希望通過上面對URL-Rewrite問題的討論,會對遇到的新問題能起到一些幫助的作用。