Apache服务器 Apache服务器原生支持了URL-Rewrite。在config中打开LoadModule rewrite_module modules/mod_rewrite.so 然后配置重写的正则表达式。例如:
摘引自Apache2.2中文参考手册 中文手册 Apache-UrlRewrite
--------------------------------------------- |
这个规则的目的是强制使用特定的主机名以代替其他名字。比如,你想强制使用www.example.com代替example.com,就可以在以下方案的基础上进行修改: |
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服务器 IIS7新的“管道模式”其实是把ASP.NET中的某些概念与IIS进行了更加深度的集成。在IIS7 Program Manager: Mike Volodarsky的Blog中有一篇文章分析了这方面的内容: Breaking Changes for ASP.NET 2.0 applications running in Integrated mode on IIS 7.0
IIS7的“经典模式”与IIS 6基本上是如出一辙的。
在IIS6 + Asp.Net应用程序级的URL-Rewrite,只能在请求被分配到Asp.Net引擎后才能发生重写操作。在IIS7这一点被改变了。IIS7可以对没有后缀名的请求进行重写,Asp.Net和IIS7进行了深度的集成。IIS7可以在 IIS 请求管道的任何地方执行一个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" />这条规则中的~/products/(.+)这条正则表达式。匹配了/products/下的所有链接。 IIS6服务器级别下的重写需要使用ISAPI Filters Rewrite来实现。
ISAPI 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 全免费开源组件。 在 ISAPI Filter编程重写URL 中有说明。
服务器级的重写与应用程序级的重写最大的区别在于他们发生的时机不同。下图是在服务器级把/Pd/Book.aspx重写到/Pd.aspx?Cg=books
请求还没有到Asp.Net引擎,就被重写了。
3.Asp.Net级别上重写的一些小细节问题(部分内容源自ScottGu 的Blog) 如果页面中存在form且form是runat=server的<form runat="server">,那么这个页面在重写后form的action是原始URL,不是重写后干净的URL。例如/Pd/Book.aspx重写到/Pd.aspx?Cg=books这个场景。实际用户浏览器访问的地址是/Pd/Book.aspx,在服务器级被重写后请求变成了/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不被重写规则匹配上,/Pd.aspx?Cg=books会被正确发回到Asp.Net引擎。但是浏览器上的地址栏会变化,暴露出真正的地址。如果这个URL被某个别的规则匹配,那就必须要求form的action被正确的Render成/Pd/Book.aspx,这种统一的重写后的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) 这种重写是当在使用Asp.Net应用程序一级的重写时,使用Context.Request.RawUrl填写form的action,当使用IIS应用服务器一级的重写时把干净的URL记录在Request.ServerVariables["HTTP_X_REWRITE_URL"]中,使用Request.ServerVariables["HTTP_X_REWRITE_URL"]填写form的action,填写form action 的过程都是通过Control Adapter对form Control扩展,override form控件的 WriteAttribute方法,在Render时重新指定form的action。
核心源代码 摘引自ScottGu的Blog
重写后路径兼容问题 在/Pd/Book.aspx重写到/Pd.aspx?Cg=books的场景中,页面中如果有相对位置的资源,如某个img的src=”../logo.gif”或src=”logo.gif”。这时浏览器请求这些资源基准的位置是/pd/也就是说src=”../logo.gif”请求的路径是/logo.gif,src=”logo.gif”请求的路径是/pd/logo.gif。但是其实这些资源的基准位置是 / 因为原始的URL是/Pd.aspx?Cg=books。这时就会发生资源找不到的情况。 1)使用服务器端的img使用 ~ 路径可以解决这个问题(源自ScottGu的Blog)。 2)使用<base href=" http://xxx/ "></base>标签,这个标签需要写在head里。告诉页面,页面中所有相对路径的基准路径是 http://xxx/ ,从而解决重写后路径失效的问题。 base标签的说明: http://www.w3school.com.cn/tags/tag_base.asp
到这里,URL-Rewrite的问题讨论完了。在实际项目中肯定还会遇到各种不同的问题,不过解决的思路,估计会是上面这些技术的组合和扩展,希望通过上面对URL-Rewrite问题的讨论,会对遇到的新问题能起到一些帮助的作用。
(责任编辑:admin) |