HTTP 重定向状态码选型:301、302、307 与 308 对比

对比 301、302、307 与 308 重定向状态码的语义差异,分析 POST 方法重写为 GET 的历史背景、搜索引擎权重继承机制与配置实践。

LJ
李建辉·前端全干工程师

· 8 分钟

本页目录展开 / 收起

读完你能做什么

  • 同时根据永久性与请求方法是否保留选择 301、302、307 或 308。
  • 为域名迁移、HTTP 到 HTTPS 和临时维护设计正确跳转。
  • 用状态码、Location、重定向链和 canonical 验证 SEO 配置。

选型时先回答两个问题:跳转是永久还是临时?原请求的方法与请求体是否必须保留?SEO 是重要结果,但不能覆盖 HTTP 语义和业务安全。

在 Web 开发中,重定向常用于域名迁移、规范化 URL(Canonicalization)以及路由兼容。

面对 301 Moved Permanently、302 Found、307 Temporary Redirect 和 308 Permanent Redirect 这四个常见状态码,不同状态码在浏览器对请求方法的篡改行为、缓存机制以及搜索引擎权重继承上各有差异。

本文梳理 30X 系列状态码的历史演进与选型场景。


30X 状态码演进与四大核心区别

TEXT
HTTP/1.0 规范历史包袱:
  [客户端发出 POST] ──301/302 重定向──► [旧浏览器擅自将重定向请求篡改为 GET!]

HTTP/1.1 严格定义补充:
  - 307 (临时重定向): 严禁改变请求方法 (POST 保持 POST)
  - 308 (永久重定向): 严禁改变请求方法 (POST 保持 POST)

核心对照矩阵

状态码HTTP 规范性质请求方法保留(POST/PUT)浏览器默认缓存搜索引擎权重传递
301HTTP/1.0永久移动 (Moved Permanently)⚠️ 常见浏览器会篡改为 GET✅ 强缓存(需显式设置)✅ 传递 90%~99% 权重
302HTTP/1.0临时移动 (Found)⚠️ 常见浏览器会篡改为 GET❌ 不缓存❌ 不传递权重(保留原 URL)
307HTTP/1.1临时重定向 (Temporary Redirect)✅ 严格保持原 Method 与 Body❌ 不缓存❌ 不传递权重
308HTTP/1.1永久重定向 (Permanent Redirect)✅ 严格保持原 Method 与 Body✅ 强缓存✅ 完整传递权重

深入机制一:POST 变 GET 的历史 Bug 与解决方案

在早期 HTTP/1.0 时代,当客户端向 /submit-order 发送 POST 请求而服务器返回 301 或 302 时,几乎所有主流浏览器都会自动把随后的重定向请求强制转为 GET /new-order,导致原本携带在 Request Body 中的 JSON 或表单数据完全丢失。

为了解决这个问题:

  • 如果是临时重定向且涉及非幂等请求(POST / PUT / DELETE):请务必使用 307;
  • 如果是永久重定向且涉及 API 接口变更:请务必使用 308。

深入机制二:SEO 权重传递与 302 网址劫持风险

  • 301 / 308:告知 Google / 百度爬虫“旧页面已永久失效,请将旧 URL 积累的所有排名、外链和权重完全转移给新 URL,并在搜索索引中用新 URL 替代旧 URL”。
  • 302 / 307:爬虫认为旧页面只是临时维护,因此继续保留旧 URL 在搜索结果中。

2. 警惕 302 网址劫持(302 Hijacking)

由于 302 临时重定向不会更新索引,历史上常有黑帽 SEO 做法:

  • 攻击者建立高权重域名 A,通过 302 重定向到你的原创内容页面 B;
  • 搜索引擎抓取到 B 的优质内容,却错误地把搜索结果的标题和点击跳转归属在域名 A 旗下;
  • 防御建议:所有长期固定的页面迁移、HTTP 强制跳 HTTPS、非 www 跳转 www 等,一律使用 301 或 308。

生产环境重定向实践配置(Nginx / Next.js)

1. Next.js next.config.ts 中的标准配置

TS
import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  async redirects() {
    return [
      // 永久 URL 结构迁移:设置 permanent: true (Next.js 默认输出 308)
      {
        source: '/old-blog/:slug',
        destination: '/posts/:slug',
        permanent: true, // 输出 308 Permanent Redirect,保障 SEO
      },
      // 临时活动页面跳转:设置 permanent: false (Next.js 默认输出 307)
      {
        source: '/campaign/spring',
        destination: '/campaign/2025',
        permanent: false, // 输出 307 Temporary Redirect
      },
    ];
  },
};
 
export default nextConfig;

2. Nginx 配置强制 HTTPS 与规范域名

NGINX
# 强制 HTTP 跳转 HTTPS (使用 301 永久重定向)
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

官方资料

工程经验小结

重定向不仅关乎 HTTP 状态码的数值,还直接影响浏览器对请求方法的篡改行为以及缓存有效期。

对于涉及表单提交或非幂等操作的 API 接口,如果继续沿用传统的 301/302,部分老客户端会将 POST 转为 GET 导致请求体参数丢失,此时应使用语义明确的 308/307。

此外,301 与 308 默认具备强缓存特性,一旦误配置了永久重定向且被浏览器或 CDN 缓存,后续撤销和修复成本极高。在不确定迁移是否最终确立前,可以先用临时重定向进行灰度验证,待路径稳定后再调整为永久重定向。

评论