0

Nginx return和rewrite参数保留区别:两种重定向方式的核心差异与实战选择

2026.05.27 | youres | 13次围观

在Nginx中做重定向时,很多人对returnrewrite的行为感到困惑,尤其是参数是否保留这个问题。实际上,两者的表现完全不同——这直接决定了你该用哪个指令。

核心差异:return 不带参数,rewrite 可以控制

这是两者最本质的区别。

return指令在处理重定向时,不会自动携带查询参数。当你配置:

return 301 https://example.com/target;

访问 https://example.com/source?foo=bar 时,浏览器最终会跳转到 https://example.com/target,而 ?foo=bar 被完全丢弃

rewrite的行为则不同。默认情况下,rewrite会保留原始的查询参数:

rewrite ^/old-page /new-page permanent;

访问 /old-page?id=123 会跳转到 /new-page?id=123,参数自动跟随。但这里有个前提:你的目标路径里不能写死查询字符串。

为什么 return 默认丢失参数?

Nginx 的return指令是直接发送 HTTP 响应头中的 Location 字段。当你在return里指定了一个 URL,这个 URL 就作为 Location 的值,Nginx 不会自动附加原始请求的查询参数。

这是符合 HTTP 规范的——Location header 本身就是完整的目标地址。但实际业务中,保留参数往往是刚需。

return 如何手动保留参数?

如果一定要用return,又想保留参数,需要用变量拼接:

location /old {
    return 301 https://example.com/new`$request_uri;
}

$request_uri 包含了原始 URI 和查询参数,这样拼接后参数就能保留。但要注意:$request_uri 是完整的路径,从/开始,如果你的目标是绝对 URL,路径部分要从头写起。

另一种写法:

return 301 https://example.com/new`$is_args`$args;

$is_args 在有参数时返回?,无参数时返回空;$args 就是查询参数字符串。这种方式更精确地控制参数部分。

rewrite 保留参数时的一个坑

很多人以为 rewrite 默认保留参数就万事大吉了,其实不然。如果你显式写了带?的目标路径,参数会被丢弃:

# 这会丢失原始参数
rewrite ^/old /new? permanent;

末尾的?告诉 Nginx 清空所有查询参数。所以如果要手动控制参数,写法上要注意。

两者性能对比

从性能角度,returnrewrite更高效——return是 Nginx 内部的直接响应,不需要经过正则匹配引擎。官方文档明确说return是 stop processing 级别的指令,执行完就结束。

但实际差异通常可以忽略不计,除非你的并发量极高。

实战场景选择建议

  • 简单跳转,参数需要保留:用 rewrite,最省事。
  • 跨域名跳转:用 return 301 + $request_uri,语义更清晰。
  • 参数需要过滤或修改:只能用 rewrite,因为 return 没法对参数做二次处理。
  • 绝对性能和简单性优先:用 return

最常见的错误场景

很多人在 HTTPS 强制跳转时这样写:

return 301 https://`$host`$request_uri;

这个配置本身是对的,能保留参数。但如果你写成了:

return 301 https://`$host/;

那所有参数就全丢了,这就是为什么很多人发现"重定向后表单数据丢了"的根本原因。

总结

Nginx 的returnrewrite在参数处理上的差异不是 bug,而是设计选择。return直接发送指定 URL,默认不带参数;rewrite在同 server 内默认保留参数,跨域名跳转时也取决于你的写法。

理解了这个本质,你就不会再踩坑了。


相关阅读:

版权声明

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

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