状态码:3xx 重定向

301/302/303/307/308 的方法改写差异、Location 解析规则与 300/304 的特殊语义。

作者 David更新于 第 9 篇(共 22 篇)

Location

Location = URI-reference

3xx 的核心字段。要点:

  • 值可以是相对引用,接收方 MUST 以请求的目标 URI 为基准解析。
  • 值中的 fragment:若 Location 自身无 fragment,客户端 SHOULD 沿用原请求 URI 的 fragment。
  • Location 在 201 中语义不同——指新建资源,不是重定向。
  • 值不做百分号解码;含非 ASCII 时必须先编码为 URI。

五个重定向码的差异

唯一需要记的维度是:后续请求是否保留原方法与请求体。

码语义后续方法缓存引入
301 Moved Permanently永久迁移可改写为 GET(历史行为)默认可缓存早期
302 Found临时可改写为 GET(历史行为)需显式早期
303 See Other去别处取结果MUST 改为 GET需显式HTTP/1.1
307 Temporary Redirect临时MUST 保留原方法与体需显式HTTP/1.1
308 Permanent Redirect永久迁移MUST 保留原方法与体默认可缓存RFC 7538

301/302 的方法改写问题

规范原意是保留方法,但历史实现普遍把 POST 后的 301/302 改写成 GET。RFC 9110 承认这一现实:允许(而非要求)改写。

后果:301/302 对非 GET 请求的行为不可预测。工程结论——

  • 需要确保改为 GET → 用 303。
  • 需要确保保留方法 → 用 307(临时)或 308(永久)。
  • 301/302 只用于 GET/HEAD 场景。

301/308 的缓存影响

两者默认可缓存且常被浏览器长期持久化(甚至无 Cache-Control 时也硬缓存到磁盘)。误发一次 301 到错误目标,用户侧可能长期无法恢复。

生产建议:新上线的永久重定向先用 302/307 观察,确认无误再改 301/308;或对 301 显式加 Cache-Control: max-age=<较小值>。

300 Multiple Choices

目标资源有多个表示,供客户端选择(主动式内容协商)。

  • SHOULD 在体中列出可选表示的清单,格式未规范化。
  • 可用 Location 指出服务端的首选项。
  • 默认可缓存。实际部署极少。

304 Not Modified

条件请求命中——客户端的缓存副本仍然有效。不是重定向,归在 3xx 是历史分类。

硬性约束:

  • MUST NOT 有消息体。响应终止于头后的空行。
  • MUST 带若与 200 一起发送时会发的验证器:ETag、Last-Modified(若有)。
  • SHOULD 带在同样情况下会发的 Cache-Control、Content-Location、Date、Expires、Vary。
  • 可带 Content-Length(指若为 200 时的长度),接收方不得据此读体。
  • 缓存收到 304 后 MUST 用响应中的头更新已存储的响应,然后把更新后的副本交给客户端。

详见条件请求。

305 与 306

  • 305 Use Proxy:已废弃(RFC 7231 起)。曾要求客户端经指定代理重发,因存在被劫持风险被移除。客户端 MUST NOT 遵循它。
  • 306:已保留不用。曾是 Switch Proxy 草案,从未标准化。

重定向循环

规范不规定最大跳数。客户端 MUST 自行检测并中断循环(常见上限 20 跳,浏览器多为 20,curl 默认 --max-redirs 50)。

跨重定向时的安全要求:

  • 跳到不同 origin 时,客户端 MUST NOT 携带原 Authorization 字段。
  • Cookie 按各自域的规则重新计算,不是照抄。

下一篇:状态码:4xx 客户端错误。

本页目录