HTTP 重定向状态码 301/302/303/307/308
理解 HTTP 重定向状态码的区别和使用场景
问题
HTTP 中的 301、302、303、307、308 状态码有什么区别?分别在什么场景下使用?
解答
状态码对比
| 状态码 | 名称 | 重定向类型 | 请求方法 |
|---|---|---|---|
| 301 | Moved Permanently | 永久 | 可能变为 GET |
| 302 | Found | 临时 | 可能变为 GET |
| 303 | See Other | 临时 | 强制变为 GET |
| 307 | Temporary Redirect | 临时 | 保持不变 |
| 308 | Permanent 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 不缓存
目录