301、302、303、307、308 这些状态码有什么区别?
3xx开头的状态码都表示重定向。
先说明一些版本问题, 301和302都是http1.0就定义好的,在http1.1中才新增了其余的状态码。
301 Moved Permanently 永久重定向
在请求的 URL 已被移除时使用。响应的 Location 首部中应该包含 资源现在所处的 URL。
默认情况下,永久重定向是会被浏览器缓存的。
302 Found 临时重定向
与 301 状态码类似;但是,客户端应该使用 Location 首部给出的 URL 来临时定位资源。将来的请求仍应使用老的 URL。
在浏览器的实现中,302默认以get重新发出请求。比如以post访问 a.com ,用302重定向到b.com,浏览器会使用get请求b.com。但这样就会导致之前的post请求数据丢失,相对的 307不允许修改请求方法,这也是302和307最大的区别
在rfc1945 中规定:
If the 302 status code is received in response to a request using the POST method, the user agent must not automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.
这段英文大意:如果对post请求返回了302状态码, 在未经用户确认的情况下不允许擅自发送请求,因为可能会修改请求条件。
在post数据量大的情况下从post改为get,肯定会丢失很多参数。但是很多浏览器都是以get方式重定向的,所以在后来的rfc7231 中取消了这一段强制要求,并将此要求放在了307状态码中。
303 See Other 临时重定向
303 是为了区分302而存在的。
维基百科:
虽然 RFC 1945 和 RFC 2068 规范不允许客户端在重定向时改变请求的方法,但是很多现存的浏览器在收到302响应时,直接使用GET方式访问在Location中规定的URI,而无视原先请求的方法。因此状态码303被添加了进来,用以明确服务器期待客户端进行何种反应。
重定向到新地址时,客户端必须使用GET方法请求新地址。
307 Temporary Redirect
这个状态码和302相似,有一个唯一的区别是不允许将请求方法从post改为get。
在rfc7231的原话如下:
Note: This status code is similar to 302 (Found), except that it does not allow changing the request method from POST to GET
308 Permanent Redirect 永久重定向
rfc7538 新增的状态码
此状态码类似于301(永久移动),但不允许更改从POST到GET的请求方法。
308是307的永久版本,和307是一对
来个总结:
永久重定向有两个: 301和308。
- 两者都默认缓存,
- 但是308不允许将请求方法从POST修改到GET, 301允许。
临时重定向三个:302,303,307
- 303强制浏览器可以将请求方法从POST修改到GET
- 307不允许浏览器修改请求方法。
- 302一开始的标准是不允许修改POST方法,但是浏览器的实现不遵循标准,标准就向现实妥协而做了修改。
另外,关于默认缓存的响应头:
Responses with status codes that are defined as cacheable by default (e.g., 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 in this specification) can be reused by a cache with heuristic expiration unless otherwise indicated by the method definition or explicit cache controls all other status codes are not cacheable by default.
这一段是在rfc7231中说明的,在 rfc7538又说明了 308是默认缓存的。