0

Nginx return 307 临时重定向参数保留:POST请求不丢失的完整配置指南

2026.05.28 | youres | 9次围观

为什么需要 307 重定向?

大多数人配置 Nginx 重定向只想到 301 和 302,但这两个状态码有个致命缺陷:301 和 302 在 HTTP/1.0 规范里要求客户端把 POST 请求改成 GET 再重定向,导致 POST 请求体直接丢失。

虽然现代浏览器对 302 的处理已经"事实上"保留了 POST,但规范并不保证。真正保证请求方法和请求体不变的,是 307 Temporary Redirect308 Permanent Redirect

301/302/307/308 核心区别

状态码是否永久是否保留请求方法是否保留POST请求体典型用途
301否(规范允许变GET)域名迁移、永久换URL
302否(规范允许变GET)临时跳转、A/B测试
307是(强制保留)临时维护、API临时切换
308是(强制保留)永久换URL且需保留POST

核心结论:需要保留 POST 请求体或查询参数做临时跳转,用 307;永久跳转且保留 POST,用 308

return 307 基础写法(保留查询参数)

return 指令的语法是 return code [text/URL],当返回的是完整 URL(以 http:// 或 https:// 开头)时,Nginx 将其作为重定向响应返回。

# 方法1:直接写完整URL(自动保留原请求参数)
location /old-api/ {
    return 307 https://www.youres.cn/new-api/;
}

# 方法2:使用  拼接(保留原始URI+参数)
location /old-api/ {
    return 307 https://www.youres.cn/new-api;
}

注意:return 307 https://www.youres.cn/new-api/; 这种方式,如果原请求是 /old-api/?token=abc,重定向后目标 URL 是 https://www.youres.cn/new-api/?token=abc查询参数自动保留

return 307 拼接查询参数的正确姿势

当需要把旧路径的参数传递到新路径时,用 拼接:

#  有参数时是 '?',无参数时是空字符串
#  是原始查询字符串
location /search {
    return 307 https://www.youres.cn/new-search;
}

对比一下几种写法的差异:

  • return 307 https://example.com/path; — 原请求的查询参数自动附加到新 URL
  • return 307 https://example.com/path?; — 显式传递参数,效果同上但更明确
  • return 307 https://example.com/path?fixed=1; — 只附加 fixed=1,原参数丢失
  • return 307 https://example.com/path?fixed=1&; — 附加固定参数+原参数

307 与 302 在 POST 请求上的实际差异

用 curl 实测一下 302 和 307 对 POST 请求的处理差异:

# 测试302重定向(POST请求会被改成GET)
curl -X POST https://www.youres.cn/old-api/ -d 'name=test' -L -v

# 测试307重定向(POST请求体保留,方法不变)
curl -X POST https://www.youres.cn/new-api/ -d 'name=test' -L -v

实测结果:302 重定向后,curl 默认把 POST 改成 GET(除非加 --post302 参数);307 重定向后,POST 请求体和请求头均保持不变。

Nginx return 307 完整配置示例

server {
    listen 443 ssl;
    server_name www.youres.cn;

    # 场景1:临时维护页面,保留原请求所有信息
    location /api/ {
        return 307 https://maintenance.youres.cn/api/;
    }

    # 场景2:HTTP API升级HTTPS,保留POST请求体
    server {
        listen 80;
        server_name api.youres.cn;
        return 307 https://api.youres.cn;
    }

    # 场景3:带固定参数+原参数一起传递
    location /old-path {
        return 307 https://www.youres.cn/new-path?source=old&;
    }
}

return 307 常见误区

误区1:认为 302 一定能保留 POST

部分浏览器(Chrome、Firefox)对 302 的处理确实保留了 POST,但这是浏览器的自选行为,不是规范保证。用 307 才是规范正确做法。

误区2:return 307 后参数丢失

如果 return 的目标 URL 是完整 URL(含 http:// 或 https://),Nginx 会自动把原请求的查询参数附加到新 URL。如果参数丢失,检查是否是代理层(CDN、负载均衡)截断了请求体。

误区3:307 对 SEO 不友好

307 是临时重定向,搜索引擎会继续使用原 URL 收录,不会传递权重。如果是永久迁移,应该用 308 而不是 307。

307 与 proxy_pass 的配合

有时候不是做重定向,而是把请求代理到另一台服务器,此时用 proxy_pass 而不是 return 307

# 代理转发(不是重定向,客户端无感知)
location /api/ {
    proxy_pass https://backend.youres.cn/api/;
    proxy_set_header Host System.Management.Automation.Internal.Host.InternalHost;
    proxy_set_header X-Real-IP ;
}

# 临时重定向(客户端感知,URL会变)
location /api-temp/ {
    return 307 https://backup.youres.cn/api/;
}

调试 return 307 重定向是否生效

用 curl 查看响应头,确认状态码和 Location 头:

# -I 只显示响应头,-L 跟随重定向
curl -I -X POST https://www.youres.cn/old-api/ -d 'a=1' 2>&1 | findstr /i "HTTP Location"

# 预期输出:
# HTTP/1.1 307 Temporary Redirect
# Location: https://www.youres.cn/new-api/

总结

  • 301/302:适合纯 GET 请求的永久/临时跳转,POST 请求体可能丢失
  • 307:临时重定向,强制保留请求方法和请求体,适合 API 临时切换、维护场景
  • 308:永久重定向,强制保留请求方法和请求体,适合需要传递 POST 的永久 URL 迁移
  • return 307 的查询参数默认自动保留,无需额外配置
  • 调试时用 curl -I -X POST 确认响应状态码是否为 307

配置 Nginx 重定向时,选对状态码比选对写法更重要。307 和 308 是现代 Web 服务里保证请求完整性的关键工具。

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
882文章数 0评论数
作者其它文章