404错误处理:重定向还是直接404?

标签: AJAX HTML HTTP JavaScript 搜索引擎 | 发表时间:2016-08-03 08:00 | 作者:Harttle
出处:http://harttle.com/

小型网站开发通常会使用某种Web应用框架,比如类似Spring、Express、Django等框架。 这些框架会给出自定义错误页面的方式。当404发生时Web框架会渲染并返回对应的错误页面。 这是最自然和直接的错误处理方式,但有时我们希望错误页面可以单独Serve,比如放到CDN上。 本文档依据RFC 2616(HTTP 1.1)比较几种常见的404错误处理方法:

  • 返回具有404信息的页面,同时给出404状态码。

    Google、Github、Facebook、Amazon、Linkedin。

  • 重定向(302/303)至错误URL,该URL给出具有404信息的页面。

    百度、淘宝、腾讯

状态码及其语义

使用最广的HTTP标准当属1999年发布的HTTP/1.1, R. T. Fielding 在2000年的博士论文 “Architectural Styles and the Design of Network-based Software Architectures” 中重申如何正确使用HTTP语义以及REST架构风格。 符合标准的HTTP消息拥有透明的、自描述的语义,通信方遵循一致的标准才使得整个互联网得以高效地运行。

HTTP状态码对用户不可见,因为Web页面返回给用户之后页面代码并非直接显示给用户, 而是经由用户代理(User Agent,比如浏览器、爬虫等)处理。 状态码的重要性在于它告诉用户代理当前页面的状态,借此用户代理才能做出正确的操作: 比如刷新当前页面,或者访问另一个URL,重置或重新提交表单等等。

HTTP状态码有很多,本文档只关心其中的404,200,以及302/303状态码。

200

请求成功。对于GET,应当返回被请求资源的实体;对于POST,应当返回操作的结果。

   RFC 2616: 10.2.1

The request has succeeded. The information returned with the response
is dependent on the method used in the request, for example:

GET   an entity corresponding to the requested resource is sent in
          the response;
POST  an entity describing or containing the result of the action;

302

被请求的资源暂时位于另一个URI处,并且对于非HEAD/GET请求, 用户代理在重定向前必须询问用户确认。

   RFC 2616: 10.3.3

The requested resource resides temporarily under a different URI.
Since the redirection might be altered on occasion, the client SHOULD
continue to use the Request-URI for future requests. This response
is only cacheable if indicated by a Cache-Control or Expires header
field.

RFC 1945 和 RFC 2068 规定客户端不允许更改请求的方法。但很多浏览器会将302当做303来处理。

303

被请求的资源暂时位于另一个URI处,并且应当以GET方法去请求那个资源。

   RFC 2616: 10.3.4

The response to the request can be found under a different URI and
SHOULD be retrieved using a GET method on that resource. This method
exists primarily to allow the output of a POST-activated script to
redirect the user agent to a selected resource. The new URI is not a
substitute reference for the originally requested resource. The 303
response MUST NOT be cached, but the response to the second
(redirected) request might be cacheable.

404

服务器未能找到URI所标识的资源。也常被用于服务器希望隐藏请求被拒绝的具体原因。 例如403、401可能会被统一处理为404。

   RFC 2616: 10.4.5

The server has not found anything matching the Request-URI. No
indication is given of whether the condition is temporary or
permanent. 

This status code is commonly used when the server does not wish to
reveal exactly why the request has been refused, or when no other
response is applicable.

直接404

直接404是常见Web框架的通用做法:对于每一个用户请求遍历所有可能的路由, 如果任何一个控制器都不处理该请求,则Web服务器返回一个具有404状态码的HTTP响应。

404状态码告诉用户代理(User Agent)请求中的URI所标识的资源不存在, 用户代理将该HTTP响应的主体(往往是HTML)显示给用户, 该HTML页面是终端用户可读的,通常也会包含Not Found信息,以及一些有用的链接。

爬虫是一种特殊的用户代理,通常用于搜索引擎。当搜索引擎的爬虫发现某URI返回404状态码时, 会认为该URI已经失效而不对它进行索引,或者将该URI标识的已索引资源移除。 所以是网站迁移时,如果一个旧的URI会位于一个新的URI处,应当使用301重定向来告知搜索引擎: 该资源并未失效只是位置发生变化。

当我们无法控制服务器返回301时,也可在返回的 HTML中使用特殊标记 来告知用户代理这是一个301,这在迁移静态站点时非常有用。

404的一个问题在于不支持CDN。如果为了提升性能使用CDN服务, 将 404.html文件托管到CDN提供商,访问该文件显然会返回200状态码。 因为CDN服务器认为你所访问的文件存在。

重定向至404页面

在国内网站中更常见的方式是将所有错误重定向至错误页面,比如 error.html。 当用户代理访问 error.html时服务器返回状态码为200,这便是神奇的 200 Not Found。 200 Not Found显然不符合HTTP语义标准,下面从搜索引擎和CDN两个方面评价该方法的优劣:

搜索引擎非常不友好。当一个页面Not Found时爬虫并不知情,因为它收到的状态码是303。 于是跟随重定向并索引了错误页面 error.html。这意味着该网站会有大量的URL都拥有同样的内容(404页面), 网站会因此受到搜索引擎的惩罚而排名下降。

另外作为程序员吐槽一下200 Not Found给调试带来的不便:

  • 脚本、样式或 AJAX 发生 404 时 Console 不显示任何错误;
  • Accept为JSON或JavaScript的AJAX请求会得到HTML响应体;
  • <script>标签404会使整个HTML失效。

国内不少公司选择重定向的错误处理方式也必有其优点:

  • 固定的错误页面可以直接托管于CDN,通过CDN统计和脚本的方式来统计错误。
  • 固定的URL可以支持更加松耦合的架构,只需约定重定向URL即可构建前后端通用的错误处理。

参考

相关 [错误 重定向] 推荐:

404错误处理:重定向还是直接404?

- - Harttle Land
小型网站开发通常会使用某种Web应用框架,比如类似Spring、Express、Django等框架. 这些框架会给出自定义错误页面的方式. 当404发生时Web框架会渲染并返回对应的错误页面. 这是最自然和直接的错误处理方式,但有时我们希望错误页面可以单独Serve,比如放到CDN上. 本文档依据RFC 2616(HTTP 1.1)比较几种常见的404错误处理方法:.

linux重定向:将标准输出stdout和标准错误stderr重定向到一个文件

- - CSDN博客系统运维推荐文章
使用&>或&>>可以将stdout和stderr一块输出到指定文件. 先重定向文件描述符A,再用B>&A或B>>&A将文件描述符B重定向到同一文件. 上面例子stderr(2)被重定向到stdout(1)当前的位置(即outerr.txt). 作者:BlueCloudMatrix 发表于2014-4-4 20:14:12 原文链接.

shell 重定向的一处妙用

- Kindy - A Geek&#39;s Page
偶然在 dracut 的代码中发现一个使用重定向很巧妙的地方. 见 modules.d/90kernel-modules/module-setup.sh 文件.                  *.ko)    [[ $(<        $_f) =~ $_blockfuncs ]] && echo "$_f" ;;.

linux各种数据流重定向

- - CSDN博客系统运维推荐文章
> :以覆盖的方法将『所有的数据』输出到指定的文件或装置上. 1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上. 1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上. 2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上. 2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上.

spring mvc 的跳转 和 重定向

- - 企业架构 - ITeye博客
(1)我在后台一个controller跳转到另一个controller,为什么有这种需求呢,是这样的. 我有一个列表页面,然后我会进行新增操作,新增在后台完成之后我要跳转到列表页面,不需要传递参数,列表页面默认查询所有的.         方式一:使用ModelAndView.         这样可以重定向到toList这个方法.

Oracle错误代码

- - 数据库 - ITeye博客
ORA-00001: 违反唯一约束条件 (.). ORA-00017: 请求会话以设置跟踪事件. ORA-00018: 超出最大会话数. ORA-00019: 超出最大会话许可数. ORA-00020: 超出最大进程数 (). ORA-00021: 会话附属于其它某些进程;无法转换会话. ORA-00022: 无效的会话 ID;访问被拒绝.

Matt Cutts 发视频详细讲述 301 重定向

- 尘世客 - 谷奥——探寻谷歌的奥秘
Google Webmaster Blog宣布SEO老大Matt Cutts除了制作以前的问答系列视频以外,还将继续制作更深入的视频指南,包含跟站长有关的重要话题. 今天的第一段视频是有关301重定向的. Matt解释了301重定向的数量是没有限制的,你可以将成千上万的网页都做301重定向让Google爬虫爬到新的地址,完全没问题.

Java重定向标准输入输出流I/O

- - Java - 编程语言 - ITeye博客
        一般情况下,System.in代表的是键盘、System.out是代表的控制台(显示器). 当程序通过System.in来获取输入的时候,默认情况下,是从键盘读取输入;当程序试图通过System.out执行输出时,程序总是输出到显示器. 如果我们想对这样的情况做一个改变,例如获取输入时,不是来自键盘,而是来自文件或其他的位置;输出的时候,不是输出到显示器上显示,而是输出到文件或其他位置,怎么实现.

10大经典错误

- beralee - 酷壳 - CoolShell.cn
下面是10、11个经典的错误,升序排名. 10、DOS的Abort,Retry, Fail. 85年以后出生的人可能不知道DOS是什么了,只有那老家伙还知道这是什么. 我还记得当时的我对于Abort和Fail这两个选择还是比较清楚的,不过,今天完全忘记了Abort和Fail的差别是什么. 这个出是DOS下的经常出现,也相当的经典,以至于在Wikepedia上都有专门的业面 Abort, Retry, Fail?.

Google Realtime出现404错误

- lube - Solidot
hidenosense 写道 "我的Google搜索页面左边工具栏里的realtime没了. 直接打开http://www.google.com/realtime返回404.