HTTP 重定向状态码 301、302、303、307、308 有什么区别?
简化版
HTTP 重定向靠 3xx 状态码和 Location 头告诉客户端去新地址。301/308 表示永久重定向,302/303/307 表示临时重定向;303 明确让客户端改用 GET,307/308 要求保留原请求方法和请求体。
详细版
常见重定向可以按两个维度记:是否永久、是否保留方法。
301 Moved Permanently:永久重定向,搜索引擎和客户端可能缓存,历史上很多客户端会把 POST 改成 GET。302 Found:临时重定向,历史兼容原因也常被客户端改成 GET。303 See Other:明确告诉客户端用 GET 访问Location,常用于表单提交后跳转结果页。307 Temporary Redirect:临时重定向,但必须保留原方法和 body。308 Permanent Redirect:永久重定向,也必须保留原方法和 body。
工程上:页面永久迁移常用 301/308;登录后跳转、临时活动页常用 302;POST 后跳详情页常用 303;API 临时迁移且不能改方法用 307,永久 API 迁移用 308。
完整版教学
一、重定向到底发生了什么
重定向不是服务器把目标页面内容直接返回,而是先返回一个 3xx 响应,并在 Location 响应头里写新地址。客户端收到后再发起第二次请求。
Client -> GET /old
Server <- 301 Location: /new
Client -> GET /new
Server <- 200 HTML
这里至少有两次 HTTP 往返。若重定向链很长,例如 /a -> /b -> /c -> /d,用户首屏会多等多次 RTT,搜索引擎也会降低抓取效率。
记忆钩子:重定向的核心不是 3xx 数字本身,而是“客户端拿到 Location 后再请求一次”。
二、永久和临时的区别
永久重定向表示资源的规范地址已经变了,客户端、浏览器缓存、搜索引擎都可以更积极地记住新地址。临时重定向表示这次先去别处,但原 URL 仍然有效。
| 状态码 | 是否永久 | 常见用途 | 缓存/SEO 含义 |
|---|---|---|---|
| 301 | 永久 | 域名迁移、URL 规范化 | 权重通常迁移到新 URL |
| 302 | 临时 | 登录跳转、临时活动 | 原 URL 仍是主地址 |
| 308 | 永久 | API 永久迁移且保留方法 | 比 301 更严格保留方法 |
举例:http://example.com 迁移到 https://example.com,通常用 301 或 308;但用户未登录访问 /orders 被跳到 /login,应该用临时重定向,不能让浏览器永久记住 /orders 等于 /login。
三、方法是否会被改写是高频坑
早期客户端对 301/302 的处理并不一致,很多会把 POST 重定向后的第二次请求改成 GET。后来 HTTP 引入 303、307、308,把语义讲清楚。
POST /pay
302 Location: /pay-new
历史兼容行为:GET /pay-new
这对支付、下单、上传接口可能很危险
如果你明确希望“提交完成后跳到结果页”,用 303 很合适;如果你希望“请求仍然是 POST,body 也要带过去”,应选 307 或 308。
四、303 为什么适合 PRG 模式
PRG 是 Post/Redirect/Get。用户提交表单后,服务端处理成功,不直接返回结果页面,而是回 303,让浏览器 GET 一个结果页。这样用户刷新结果页时,不会重复提交 POST。
POST /orders -> 创建订单
303 Location: /orders/1001
GET /orders/1001 -> 展示订单结果
这个模式能降低“刷新页面重复下单”的风险。注意它不是幂等性的替代品,后端仍要有幂等键或去重机制。
五、307 和 308 为什么对 API 更安全
API 请求通常在方法和 body 上有明确语义。POST、PUT、PATCH 如果被重定向后变成 GET,请求体丢失,服务端行为就变了。307/308 的价值就是强制保留原方法和请求体。
| 场景 | 推荐状态码 | 原因 |
|---|---|---|
| 临时把上传接口切到新域名 | 307 | 保留 POST 和文件 body |
| 永久迁移 PUT API | 308 | 保留方法且语义永久 |
| 表单提交后看结果页 | 303 | 明确转 GET |
| 旧文章 URL 永久迁移 | 301 | SEO 友好 |
面试时能说出“307/308 是为了解决 301/302 历史方法改写问题”,就比只背状态码更像工程回答。
六、重定向的工程注意事项
重定向会影响性能、安全和缓存。性能上要避免多级跳转;安全上要防开放重定向;缓存上要谨慎使用永久重定向,因为浏览器可能记住很久。
坏链路:
http://a.com -> https://a.com -> https://www.a.com -> /home
更好:
http://a.com -> https://www.a.com/home
开放重定向示例是 /login?next=https://evil.com。如果服务端不校验 next,用户登录后被跳到恶意网站,钓鱼风险很高。
七、常见误区与追问
- 误区:301 和 302 只是名字不同。 301 是永久语义,302 是临时语义,缓存和 SEO 影响明显不同。
- 误区:所有重定向都会保留 POST。 301/302 在历史兼容中可能改成 GET,307/308 才明确要求保留方法和 body。
- 误区:重定向越多越灵活。 多级重定向增加 RTT,影响首屏和搜索引擎抓取。
- 追问:POST 成功后为什么常用 303? 让浏览器用 GET 打开结果页,避免刷新导致重复提交。
- 追问:API 临时迁移用 302 还是 307? 若必须保留方法和请求体,应使用 307。
- 追问:开放重定向有什么风险? 攻击者可借可信域名跳到恶意站点,常用于钓鱼和登录劫持。
八、加强记忆
重定向按“永久性 + 方法保留”记:301/308 是永久,302/303/307 是临时;303 明确转 GET,307/308 保留原方法和 body。页面迁移看 SEO,表单成功看 303,API 迁移优先考虑 307/308。