对 HTTP 有所了解的人,大概都清楚 3 开头的响应状态码都表示重定向的响应。但是具体细节究竟是什么,看似类似的效果,在本质上究竟有什么不同?

如果你不能说清楚标题中五个状态码的具体差别,那么这篇文章应该会帮到你。

首先先来看一下,HTTP 中这五个响应状态码的名字:

根据 RFC 7231

  • 301 Moved Permanently

  • 302 Found

  • 303 See Other

  • 307 Temporary Redirect

根据 RFC 7538

  • 308 Permanent Redirect

从名字可以看出来,301、308 是永久重定向,剩下的三个不一定能从名字看出来作用是什么,所以干脆记住它们都是临时重定向就好了。

302、303 与 307

我们从临时重定向开始,先放上它们 302、303、307 最新的定义,之后再去解释这些重定向之间的差别。(这些定义并不是对 RFC 文档的逐字翻译,为了解释清楚我会省略或转述一些信息。)

302 Found 的定义

302 状态码表示目标资源临时移动到了另一个 URI 上。由于重定向是临时发生的,所以客户端在之后的请求中还应该使用原本的 URI。

服务器会在响应 Header 的 Location 字段中放上这个不同的 URI。浏览器可以使用 Location 中的 URI 进行自动重定向。

注意:由于历史原因,用户代理可能会在重定向后的请求中把 POST 方法改为 GET 方法。如果不想这样,应该使用 307(Temporary Redirect) 状态码。(之后我们会详细叙述历史原因)

303 See Other 的定义

303 状态码表示服务器要将浏览器重定向到另一个资源,这个资源的 URI 会被写在响应 Header 的 Location 字段。从语义上讲,重定向到的资源并不是你所请求的资源,而是对你所请求资源的一些描述。

303 常用于将 POST 请求重定向到 GET 请求,比如你上传了一份个人信息,服务器发回一个 303 响应,将你导向一个“上传成功”页面。

不管原请求是什么方法,重定向请求的方法都是 GET(或 HEAD,不常用)。


到这里你可能发现,303 和 302 的作用很类似,除去语义差别,似乎是 302 包含了 303 的情况。确实,这是由历史原因导致的。我们先来看一下 307 的效果。


307 Temporary Redirect 的定义

307 的定义实际上和 302 是一致的,唯一的区别在于,307 状态码不允许浏览器将原本为 POST 的请求重定向到 GET 请求上。

302 与 303、307 的关系

区别

在这里总结一下,从实际效果看:302 允许各种各样的重定向,一般情况下都会实现为到 GET 的重定向,但是不能确保 POST 会重定向为 POST;而 303 只允许任意请求到 GET 的重定向;307 和 302 一样,除了不允许 POST 到 GET 的重定向。

简要历史原因

那为什么有了 307 和 303 还需要 302呢?把总结放在最前面。302 在最初的定义中,内容和现在的 307 是一样的,不允许重定向方法的改写(从 POST 到 GET,由于 GET 不应该有 body,实际上 body 也被改了)。但是早期浏览器在实现的时候有的实现成 303 的效果,有的实现成 307 的效果。于是在之后的标准,302 在某些浏览器中错误的实现被写进规范,成为 303,而 302 原本的效果被复制了到了 307。在最近的一次标准修订中,302 标准被修改成不再强制需要维持原请求的方法。所以就产生了现在的 302、303 和 307

详细的历史原因(可以跳过)

在 1995 年 6 月的 RFC 1945 HTTP 1.0 标准,302 被称为 Moved Temporarily,而不是现在的 Found。标准中提到,有些浏览器收到了 302 状态码,在自动重定向时候会错误的把 POST 方法转为 GET 方法:

Note: When automatically redirecting a POST request after
receiving a 302 status code, some existing user agents will
erroneously change it into a GET request.

这个错误在 1997 年 1 月的 RFC 2068 HTTP 1.1 标准提出时,仍然没有被修正。此时标准中依然只有 302 Moved Temporarily。

但是谁知道两年多过去了,浏览器厂商们懒得改。那既然厂商不改,就标准改吧。

在 1999 年 6 月的 RFC 2616 中,增加了 303 与 307,与此同时 302 被更名为 Found。标准中提到:

Note: RFC 1945 and RFC 2068 specify that the client is not allowed
to change the method on the redirected request. However, most
existing user agent implementations treat 302 as if it were a 303
response, performing a GET on the Location field-value regardless
of the original request method. The status codes 303 and 307 have
been added for servers that wish to make unambiguously clear which
kind of reaction is expected of the client.

简单来说,就是之前的标准都写了不允许重定向的时候改写方法,但是大多数浏览器还把 302 当成 303 那样处理。那干脆把两种不同的行为区分成 303 和 307。

302 标准就被那么放着了。

最终,2014 年 6 月的 RFC 7231 中,修改了对 302 的定义:

The user agent MAY use the Location field value for automatic redirection.

在之前的标准中,这句话中的 MAY 都是 MUST NOT。标准妥协了,既然现在大多数浏览器都支持了 307 和 303,那 302 的标准也就改了吧。

这就是 303、307 与 302 的关系。

301 与 308

有了之前的对 302、303、307 的理解,对 301 和 308 的理解就简单多了。

301 Moved Permanently 的定义

301 状态码表明目标资源被永久的移动到了一个新的 URI,任何未来对这个资源的引用都应该使用新的 URI。

308 Permanent Redirect 的定义

308 的定义实际上和 301 是一致的,唯一的区别在于,308 状态码不允许浏览器将原本为 POST 的请求重定向到 GET 请求上。

301 与 308 的历史

和 302 一样,301 在浏览器中的实现和标准是不同的,这个时间一直延续到 2014 年的 RFC 7231,301 定义中的 Note 还是提到了这个问题。直到 2015 年 4 月,RFC 7538 提出了 308 的标准,类似 307 Temporary Redirect 之于 302 Found 的存在,308 成为了 301 的补充。

一点额外补充

临时重定向和永久重定向对搜索引擎会产生不同的效果。


到这里,301、302、303、307、308 的关系大致就能理清了。希望这篇文章能让你更好的理解这几个 HTTP 响应状态码。

HTTP 中的 301、302、303、307、308 响应状态码相关推荐

  1. 详解重定向(HTTP状态码301/302/303/307/308)附案例

    关注 前端瓶子君,回复"交流" 加入我们一起学习,天天进步 今天打算好好把状态码301.302.303.307.308好好撸一遍,并会测试下一些例子. 状态码的解释 我们都知道重定 ...

  2. http 301 302 303 307 308 傻傻分不清

    http的重定向我们经常是张口就来,"小明,在nginx上做一个重定向就行了".整个流程非常简单,服务端HTTP返回码是30x,头里面的Location字段代表新的URL.如下图所 ...

  3. php 303,HTTP 的重定向301,302,303,307(转)

    301 永久重定向,告诉客户端以后应从新地址访问. 302 作为HTTP1.0的标准,以前叫做Moved Temporarily ,现在叫Found. 现在使用只是为了兼容性的处理,包括PHP的默认L ...

  4. 【HTTP】http重定向301/302/303/307

    一.概述 重定向常常和请求转发放在一起讨论(前者是两次不相关的请求,后者是一次请求服务器端转发),然而本文并不讨论两者的区别,而是HTTP 1.0规范和HTTP 1.1规范中关于重定向的区别,以及实际 ...

  5. HTTP协议响应状态码(301、302、303的区别)

    1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 100 (继续) 请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101 (切换协议) 请 ...

  6. HTTP协议---HTTP请求中的常用请求字段和HTTP的响应状态码及响应头

    http://blog.csdn.net/qxs965266509/article/details/8082810 用于HTTP请求中的常用请求头字段 Accept:用于高速服务器,客户机支持的数据类 ...

  7. Java中HTTP响应状态码

    响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态. 1. 状态码都是3位数字 2. 分类: 1. 1xx:服务器接收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码 2. 2x ...

  8. http协议状态码3xx系列(301,302,303,304,305,306,307),小白易通

    3xx 重定向 3xx系列是http响应包中重要的状态标准,表示重定向意义的一类状态码,这些转状态码将指导客户端执行某些行为 都是属于重定向,但不同的值,差异却不小,具体差异如下 301 永久重定向 ...

  9. http 状态码 301 302 303 区别

    301 永久性重定向,该状态码表示请求的资源已被分配了新的URL,以后应使用资源现在所指的URL 302 临时重定向.表示请求的资源已被分配了新的URL,希望用户本次使用新的URL访问.和301相似, ...

最新文章

  1. ES6系列--对象扩展
  2. html实现照片添加功能,HTML5 Canvas调用手机拍照功能实现图片上传功能(图文详解上篇)...
  3. mysql基础(DQL语言、DML语言、DDL语言)详解
  4. Gentoo 安装日记 01 (工具准备)
  5. python自动化开发是什么_Python自动化开发学习6
  6. matlab的grayscale,Python 是否等效于Matlab函数“imfill”的grayscale??
  7. ES6笔记 -- 变量/语句声明
  8. python在scatter中添加图例_如何向matplotlib散点图添加图例
  9. Linux ---- 安装虚拟机
  10. unity xlua 在vs2019下断点调试(babelua)
  11. ffmpeg学习日记5-使用ffmpeg进行h264解码
  12. 解决ubuntu16.04无法打开网易云音乐
  13. 好佳居软装十大品牌 软装类型对应着主人
  14. Debian之CA认证
  15. conan入门(二):conan 服务配置-密码管理及策略
  16. 找到所有数组中消失的数字_【一点资讯】千万程序员的呼声:面试如何拿到大厂Offer?这份阅读量超过11W+的算法刷题宝典请你原地查收 www.yidianzixun.com...
  17. 可视计算机应用李桂清,华南理工大学研究生导师介绍---李桂清
  18. 吃亏的程序员,是如何拿到了 9 个月的年终奖?
  19. RNC/SGSN/PDP/IUPS概念
  20. MAC安装jmeter以及JDK配置

热门文章

  1. Adaptive AUTOSAR (AP) 平台设计(3)——操作系统
  2. 怎么写标题更加吸引人(几种吸引人的标题类型写法)
  3. AJAX+PHP+MySQL搜索(亲测可用附源码)
  4. android打开系统相机分别获得原图和缩略图
  5. android自定义控件的惯性滑动
  6. 为远程设计团队构建辛辣的设计工具堆栈
  7. 16种常用的数据分析方法-判别分析
  8. 菲波那切数列求解通项公式
  9. mercury怎么设置虚拟服务器,XAMPP邮件服务器Mercury的设置方法
  10. 基于java的微信小程序的实现(八)用户点赞/取消点赞功能相关后端接口开发