如何防止Nginx对重写后的URI进行自动编码?
Nginx rewrite 特殊字符自动编码问题解决方案
问题现象
当前使用的nginx.conf配置如下:
rewrite ^ $args?; rewrite url=(.*) "$1" break; proxy_pass http://proxy_backend;
规则匹配得到的$1取值为类似https://google.com/?arg=value的URL,需要将该值原样传递给proxy_backend后端服务,但实际Nginx转发的请求为GET https://google.com/%3Farg=value,URL中的问号被自动编码为%3F。
问题原因
Nginx解析rewrite规则替换字符串时,仅会识别替换串里**字面量写入的?**作为URI路径与查询参数的分隔符。如果?是从捕获变量(如当前配置里的$1)中读取的内容,Nginx会将其判定为路径段的非法普通字符,自动做URL编码转义为%3F,不会将?后的内容识别为查询参数。
修复配置(兼容所有Nginx稳定版本)
核心思路是提前拆分捕获值里的路径段和查询参数段,避免变量中携带的?被误识别为路径字符,和原配置逻辑完全对齐:
# 对齐原配置第一行rewrite的逻辑,清空原有请求参数 set $args ''; # 正则拆分url参数值:分别捕获不含?的路径部分、?后的查询参数部分 if ($args ~* url=([^?]+)(?:\?(.*))?$) { set $proxy_uri_path $1; set $proxy_uri_args $2; # 字面量写?,告知Nginx此处为路径和参数的分隔点,清空原有冗余参数 rewrite ^ $proxy_uri_path? break; # 把拆分出的查询参数赋值给内置参数变量,转发时会自动正确拼接 set $args $proxy_uri_args; } proxy_pass http://proxy_backend;
效果说明
配置重载后,Nginx转发的请求会自动将查询参数拼接到路径后,不会对?做编码,最终转发的请求行格式为GET https://google.com/?arg=value,符合原样传递的要求。
注意:如果你的Nginx版本高于1.17.9,也可以通过变量直接传给
proxy_pass实现相同效果,上述配置是兼容性最高的通用方案,不需要依赖第三方模块或高版本特性。
内容的提问来源于stack exchange,提问作者user19327611
相关产品推荐
相关产品推荐

