使用URL Rewrite模块处理404错误,相比<httpErrors>/<customErrors>有何弊端?
问题
我配置了多个重写规则,涵盖在URL中设置默认语言(en/fr)以及重写实际页面等场景。但由于这些重写规则,我的<httpErrors>或<customErrors>配置无法正常生效。因此我添加了以下重写规则:
<rule name="Redirect404" stopProcessing="true"> <match url=".*" /> <conditions> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> <add input="{URL}" pattern="/enrolment(/fr|/en)(/)?" /> </conditions> <action type="Redirect" url="/enrolment{C:1}/404-not-found" /> </rule>
同时我的404.aspx页面包含如下代码,以标识响应类型为404:
protected void Page_Load(object sender, EventArgs e) { Response.TrySkipIisCustomErrors = true; Response.Status = "404 Not Found"; Response.StatusCode = 404; }
请问与使用<httpErrors>或<customErrors>相比,这种处理404错误的方法是否存在弊端?若存在,具体是什么?
分析与解答
咱们来拆解一下这种自定义重写+页面代码的404处理方式,和原生的<httpErrors>/<customErrors>相比,确实存在不少明显弊端:
违反HTTP规范,拖累SEO表现:你的重写规则是把404请求重定向到错误页面,这会先返回3xx状态码(比如302临时重定向),再返回404。但按照HTTP规范,当资源不存在时应该直接返回404状态码,不需要额外重定向。搜索引擎爬虫会误判原URL是“已移动”而非“不存在”,这会干扰页面的索引状态,对SEO很不友好。
覆盖范围有限,无法全局处理:看规则里的条件,它只对
/enrolment路径下的多语言URL生效,应用里其他路径的404错误(比如根目录下的无效URL、其他业务页面的错误路径)都不会被这个规则处理,还是会出现原生错误配置失效的问题,没法实现全局统一的404体验。维护成本更高,易引发冲突:你需要同时维护重写规则和
404.aspx的后端代码,后续如果要新增语言、调整错误页面路径,或者扩展处理其他错误类型(比如403、500),都要分别修改两处内容。而原生的<httpErrors>/<customErrors>是集中式配置,修改起来更简洁,也不容易和其他重写规则产生冲突。存在循环重定向风险:如果
/enrolment{C:1}/404-not-found这个路径本身因为配置错误、文件丢失等原因触发了404,就会陷入无限循环重定向,导致浏览器直接报错。而原生错误处理机制有内置的防护逻辑,能避免这类问题。错误体验割裂,一致性缺失:原生配置可以统一处理所有HTTP错误类型,给用户一致的错误体验。但你的方案只针对特定路径的404,其他错误(比如服务器内部错误500、权限不足403)还是会显示IIS或ASP.NET的默认错误页面,整个应用的错误体验是割裂的。
内容的提问来源于stack exchange,提问作者MPaul

