HTTP 重定向状态码 301/302/303/307/308

理解 HTTP 重定向状态码的区别和使用场景

问题

HTTP 中的 301、302、303、307、308 状态码有什么区别?分别在什么场景下使用?

解答

状态码对比

状态码名称重定向类型请求方法
301Moved Permanently永久可能变为 GET
302Found临时可能变为 GET
303See Other临时强制变为 GET
307Temporary Redirect临时保持不变
308Permanent Redirect永久保持不变

301 Moved Permanently

永久重定向。资源已永久移动到新位置,浏览器会缓存这个重定向。

# Nginx 配置示例:HTTP 跳转 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://example.com$request_uri;
}
// Node.js 示例
res.writeHead(301, { Location: 'https://new-domain.com/page' });
res.end();

注意:浏览器可能将 POST 请求改为 GET 请求。

302 Found

临时重定向。资源临时移动,下次请求仍应使用原 URL。

// Express 示例
app.get('/old-page', (req, res) => {
  res.redirect(302, '/new-page');
});

问题:早期浏览器实现不一致,可能将 POST 改为 GET。这是历史遗留问题,后来引入了 303 和 307 来明确行为。

303 See Other

临时重定向,强制使用 GET 请求新 URL。常用于 POST 请求后重定向到结果页。

// 表单提交后重定向到结果页
app.post('/submit-form', (req, res) => {
  // 处理表单数据
  saveData(req.body);
  
  // 使用 303 重定向到结果页,浏览器会用 GET 请求
  res.redirect(303, '/success');
});

307 Temporary Redirect

临时重定向,保持原请求方法。POST 请求重定向后仍是 POST。

// API 临时迁移,保持 POST 方法
app.post('/api/v1/users', (req, res) => {
  res.redirect(307, '/api/v2/users');
  // 客户端会用 POST 方法请求新地址,并携带原请求体
});

308 Permanent Redirect

永久重定向,保持原请求方法。相当于 301 的”方法不变”版本。

// API 永久迁移,保持原方法
app.all('/api/old/*', (req, res) => {
  const newPath = req.path.replace('/api/old', '/api/new');
  res.redirect(308, newPath);
});

实际应用示例

const express = require('express');
const app = express();

// 场景1:网站改版,旧页面永久跳转(用 301)
app.get('/old-blog/:id', (req, res) => {
  res.redirect(301, `/blog/${req.params.id}`);
});

// 场景2:表单提交后跳转(用 303)
app.post('/login', (req, res) => {
  // 验证登录...
  res.redirect(303, '/dashboard');
});

// 场景3:API 临时维护,保持方法(用 307)
app.use('/api/v1', (req, res) => {
  res.redirect(307, req.url.replace('/api/v1', '/api/v2'));
});

// 场景4:HTTPS 强制跳转(用 301)
app.use((req, res, next) => {
  if (!req.secure) {
    return res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
  next();
});

app.listen(3000);

关键点

  • 301 vs 308:都是永久重定向,301 可能改变方法,308 保持方法不变
  • 302 vs 307:都是临时重定向,302 行为不确定,307 明确保持方法
  • 303:专门用于 POST 后重定向到 GET 页面(PRG 模式)
  • SEO 影响:301/308 会传递权重到新 URL,302/303/307 不会
  • 浏览器缓存:301/308 会被缓存,302/303/307 不缓存