在博客程序的日志中经常会出现这样的错误日志:
Url: http://www.cnblogs.com/cmt/p/sokcet_memory_leak.html (这个URL仅是示例)
UserAgent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
System.Web.HttpException (0x80004005)
在 System.Web.CachedPathData.ValidatePath(String physicalPath)
在 System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)
从错误内容看,应该是请求的URL路径不对,可是通过Request.Url.AbsoluteUri记录的URL又是正确的,让人丈二和尚摸不着头脑。
这个问题存在已久,之前选择了默默地忍受。今天又看到这个错误,突然觉得甚是烦人,不想再忍受,于是决定查出问题真相,并将之消灭。
。。。
在Stackoverflow上的一个回答中找到了解决方法:
<httpRuntime relaxedUrlToFileSystemMapping="true" />
原来在默认情况下,ASP.NET会对请求的URL路径进行检查,如果不符合要求,就会抛出System.Web.HttpException (0x80004005)异常。
而我们遇到的问题场景是URL以空格结尾(%20),不符合ASP.NET的URL路径验证规则,于是抛出异常,并返回500错误。但是ASP.NET在抛出异常的同时,会自作聪明地将空格从路径中去掉,从而造成Request.Url得到的是去掉空格的URL,产生了误导信息,给分析问题形成了干扰。
对于文中开头的日志内容,Googlebot实际请求的URL是:http://www.cnblogs.com/cmt/p/sokcet_memory_leak.html%20。只要将relaxedUrlToFileSystemMapping设置为true,就能避开ASP.NET的URL路径合法性检查,让ASP.NET直接返回404错误。
然后可以通过URL重写,将错误的URL重定向至正确的URL,500错误转身变成了301重定向。URL重写规则示例如下:
<rule name="html_url_fix" enabled="true" stopProcessing="true"> <match url="([^.]+.html)[^?#]+" /> <action type="Redirect" url="{R:1}" /> </rule>
既然用了URL重写,是不是可以不用多此一举——加relaxedUrlToFileSystemMapping="true"?但事实证明这样是不可取的,如果不加,访问时不会自动进行跳转,而是显示下面的页面:
这不知道是ASP.NET还是IIS干的勾当,为什么要出现这样不友好的提示页面,这里就不进行探查了。
所以,消灭这个问题的完美解决方法是:relaxedUrlToFileSystemMapping="true" + URL Rewrite。