🎯 什么是 HTTP 重定向?
重定向:服务器告诉浏览器 "你要访问的内容在另一个地址,请去那里访问"
用户请求 → http://old.com
↓
服务器响应 → "资源已移动到 http://new.com"
↓
浏览器自动 → 访问 http://new.com
📊 重定向的分类
按实现方式分类
1. 服务器端重定向(HTTP状态码)✅ 推荐
└─ 301, 302, 303, 307, 308
2. 客户端重定向(HTML/JS)
└─ <meta> 标签、JavaScript
按持久性分类
永久重定向(Permanent)
└─ 301, 308
临时重定向(Temporary)
└─ 302, 303, 307
🔢 常用状态码详解
1️⃣ 301 Moved Permanently(永久重定向)
含义: 资源已永久移动到新位置
特点:
✅ 搜索引擎会更新索引(旧URL权重转移到新URL)
✅ 浏览器会缓存重定向
✅ POST请求可能变成GET(历史遗留问题)
使用场景:
网站更换域名
URL 结构永久性改变
HTTP → HTTPS(配合 HSTS)
旧页面永久废弃
示例:
HTTP/1.1 301 Moved Permanently
Location: https://new.example.com/page
Nginx 配置:
server {
listen 80;
server_name old.example.com;
return 301 https://new.example.com$request_uri;
}
2️⃣ 302 Found(临时重定向)
含义: 资源临时位于另一个位置
特点:
✅ 搜索引擎不会更新索引
✅ 浏览器不会缓存重定向
⚠️ POST请求可能变成GET(不符合规范但浏览器这样做)
使用场景:
临时维护页面
A/B 测试
临时活动页
根据条件跳转
示例:
HTTP/1.1 302 Found
Location: https://example.com/temporary-page
应用示例(维护模式):
server {
listen 80;
server_name example.com;
# 维护模式
if (-f $document_root/maintenance.html) {
return 302 /maintenance.html;
}
}
3️⃣ 307 Temporary Redirect(临时重定向 - 严格版)
含义: 临时重定向,严格保持原请求方法
与 302 的区别:
302: POST → 可能变成 → GET ❌
307: POST → 保持为 → POST ✅
特点:
✅ 不改变请求方法
✅ 不改变请求体
✅ 适合 POST/PUT/DELETE 等请求
使用场景:
表单提交重定向
API 临时迁移
需要保持 POST 的场景
示例:
POST /api/old HTTP/1.1
Host: example.com
↓ 服务器返回
HTTP/1.1 307 Temporary Redirect
Location: https://example.com/api/new
↓ 浏览器重新发送
POST /api/new HTTP/1.1 ← 仍然是 POST!
Host: example.com
4️⃣ 308 Permanent Redirect(永久重定向 - 严格版)
含义: 永久重定向,严格保持原请求方法
与 301 的区别:
301: POST → 可能变成 → GET ❌
308: POST → 保持为 → POST ✅
特点:
✅ 不改变请求方法
✅ 搜索引擎更新索引
✅ 浏览器缓存重定向
✅ HTTP/1.1 新增(2015年)
使用场景:
API 永久迁移
需要保持请求方法的永久跳转
示例:
location /api/v1/ {
return 308 /api/v2$request_uri;
}
5️⃣ 303 See Other(查看其他位置)
含义: 重定向到另一个 URI,使用 GET 方法
特点:
✅ 明确指示浏览器使用 GET
✅ 常用于 POST 后重定向(PRG模式)
✅ 避免表单重复提交
使用场景:
POST 提交后跳转(防止刷新重复提交)
PRG 模式(Post-Redirect-Get):
步骤1: 用户提交表单
POST /submit
↓
步骤2: 服务器处理数据
保存到数据库
↓
步骤3: 返回 303
HTTP/1.1 303 See Other
Location: /success
↓
步骤4: 浏览器用 GET 访问
GET /success ← 刷新页面不会重复提交!
代码示例(Express):
app.post('/submit', (req, res) => {
// 处理表单数据
saveToDatabase(req.body);
// 303 重定向
res.redirect(303, '/success');
});
📋 状态码对比表
🔧 实际配置示例
场景1:HTTP → HTTPS(301永久)
Nginx:
server {
listen 80;
server_name example.com www.example.com;
# 永久重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL配置...
# HSTS头
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
}
Apache:
<VirtualHost *:80>
ServerName example.com
Redirect 301 / https://example.com/
</VirtualHost>
场景2:www → 非www(301永久)
Nginx:
server {
listen 80;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
场景3:旧路径 → 新路径
Nginx:
location /old-blog/ {
return 301 /blog$request_uri;
}
location = /old-page.html {
return 301 /new-page.html;
}
# 正则匹配
location ~ ^/products/(\d+)$ {
return 301 /items/$1;
}
Apache (.htaccess):
# 单个页面重定向
Redirect 301 /old-page.html /new-page.html
# 整个目录
RedirectMatch 301 ^/old-blog/(.*) /blog/$1
# 使用 mod_rewrite
RewriteEngine On
RewriteRule ^products/(\d+)$ /items/$1 [R=301,L]
场景4:维护模式(302临时)
Nginx:
server {
listen 80;
server_name example.com;
set $maintenance 0;
# 检查维护标志文件
if (-f /var/www/maintenance.flag) {
set $maintenance 1;
}
# 排除维护页面本身
if ($uri = /maintenance.html) {
set $maintenance 0;
}
if ($maintenance = 1) {
return 302 /maintenance.html;
}
# 正常配置...
}
场景5:移动端检测(302临时)
Nginx:
server {
listen 80;
server_name example.com;
# 检测移动设备
if ($http_user_agent ~* (mobile|android|iphone|ipad)) {
return 302 https://m.example.com$request_uri;
}
# 桌面端正常访问
}
场景6:语言/地区重定向(302临时)
Nginx:
server {
listen 80;
server_name example.com;
# 根据 Accept-Language 重定向
location = / {
if ($http_accept_language ~* "zh") {
return 302 /zh/;
}
if ($http_accept_language ~* "ja") {
return 302 /ja/;
}
# 默认英文
return 302 /en/;
}
}
🎨 客户端重定向方式
虽然不推荐,但也需要了解:
1. HTML Meta 标签
<!-- 3秒后跳转 -->
<meta http-equiv="refresh" content="3;url=https://example.com">
<!-- 立即跳转 -->
<meta http-equiv="refresh" content="0;url=https://example.com">
❌ 缺点:
SEO 不友好
用户体验差
无法被爬虫正确处理
2. JavaScript 重定向
// 立即跳转
window.location.href = 'https://example.com';
// 或
window.location.replace('https://example.com'); // 不记录历史
// 延迟跳转
setTimeout(() => {
window.location.href = 'https://example.com';
}, 3000);
❌ 缺点:
依赖 JavaScript
禁用 JS 的用户无法跳转
SEO 不友好
🧪 重定向链问题
什么是重定向链?
用户访问: http://example.com
↓ 301
跳转到: http://www.example.com
↓ 301
跳转到: https://www.example.com
↓ 301
跳转到: https://www.example.com/
↓
最终页面
问题:
❌ 增加页面加载时间(每次重定向 = 一次往返)
❌ 浪费爬虫配额
❌ 可能损失部分 SEO 权重
❌ 用户体验差
解决方案:
server {
listen 80;
server_name example.com www.example.com;
# 一步到位!
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
# 去除 www
return 301 https://example.com$request_uri;
}
🔍 如何查看重定向
Chrome 开发者工具
1. 打开开发者工具(F12)
2. Network 标签
3. 勾选 "Preserve log"
4. 访问页面
5. 查看状态码 301/302/307/308
6. 点击请求查看 Location 头
cURL 命令
# 显示重定向
curl -I http://example.com
# 跟随重定向
curl -L http://example.com
# 显示所有重定向步骤
curl -L -v http://example.com 2>&1 | grep "< HTTP\|< Location"
在线工具
Redirect Checker: https://httpstatus.io/
⚠️ 常见问题与最佳实践
1. 选择正确的状态码
永久性改变 → 301 或 308
临时性改变 → 302 或 307
POST后跳转 → 303
2. 避免重定向循环
# ❌ 错误示例
location / {
return 301 /page;
}
location /page {
return 301 /; # 形成循环!
}
# ✅ 正确做法
location / {
return 301 /page;
}
location /page {
# 正常处理
}
3. 处理查询参数
# 保留查询参数
return 301 https://new.com$request_uri;
# 添加新参数
return 301 https://new.com$request_uri?source=redirect;
# 移除所有参数
return 301 https://new.com$uri;
4. 相对路径 vs 绝对路径
# ✅ 推荐:绝对路径
Location: https://example.com/new-page
# ⚠️ 相对路径(可能有兼容问题)
Location: /new-page
5. 监控重定向性能
// 使用 Performance API
const redirectCount = performance.navigation.redirectCount;
console.log(`重定向次数: ${redirectCount}`);
📈 SEO 影响
301 vs 302 的 SEO 差异
301 永久重定向:
✅ 90-99% 的权重转移
✅ 搜索引擎更新索引
✅ 旧 URL 最终从索引中移除
302 临时重定向:
❌ 权重不转移
❌ 搜索引擎保留旧 URL
❌ 可能导致内容重复问题
Google 官方建议
✅ 网站迁移使用 301
✅ 保持重定向至少 6 个月
✅ 更新内部链接指向新 URL
✅ 在 Google Search Console 提交地址更改
❌ 不要使用 JavaScript 重定向
🎯 总结
决策树
需要重定向?
↓
是否永久?
├─ 是 → 需要保持请求方法?
│ ├─ 是 → 308
│ └─ 否 → 301
└─ 否 → 什么场景?
├─ POST后跳转 → 303
├─ 需保持方法 → 307
└─ 普通临时 → 302
最佳实践清单
✅ 优先使用服务器端重定向
✅ 减少重定向链(最多1-2次)
✅ 使用绝对 URL
✅ 正确选择状态码
✅ 监控重定向性能
✅ 配合 HSTS 使用(HTTPS)
✅ 更新 sitemap 和内部链接
❌ 避免重定向循环
❌ 避免过多客户端重定向
快速记忆口诀
301永久换,SEO权重传
302临时用,原址仍保留
303表单提,POST变GET妙
307临时严,方法不能变
308永久严,既久又不变