关于NGINX转发时的URI规范化
问题描述
当前经过 encodeURI,多数 MVC 框架已经能够正常工作而无需担心特殊字符集的问题。
而如果直接在路径上携带入[]|等字符,MVC 框架会根据自己的情况返回错误的 http 状态码
而一般的 http client 也会自行将 uri 编码,在服务端与客户端都已经做好对应的操作的前提下,仍有可能因为特殊字符导致不可访问的情况。
当使用 nginx 进行转发的时候,如果转发服务带上 request_uri,哪怕是/,如
1 | http://example.com/ |
那么 nginx 解析请求会进行 decode,此时特殊字符将直接被传递到目标服务,引发错误
If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:
如果使用 URI 指定了 proxy_pass 指令,那么当请求传递到服务器时,与该位置匹配的规范化请求 URI 的一部分将被该指令中指定的 URI 代替:
1 | set $modified_uri $request_uri; |
目前在 nginx 的新版本已经不用再担心该问题,至少在 1.20.1 以上版本,Nginx 并不会再出现因 proxy_pass 指令带上 URI 导致特殊字符传递导致报错的问题
解决方法
nginx 反向代理不使用/
1 | http://example.com |
nginx 对 uri 会直接转发,只需客户端本身已经做了 encode,便能够避免问题。
If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
如果指定 proxy_pass 时不带 URI,则将请求 URI 以与客户端在处理原始请求时发送的格式相同的形式传递给服务器,或者在处理更改的 URI 时传递完整的规范化请求 URI:
rewrite
1 | location /foo { |
目标服务自身的变更(Spring Boot)
1 |
|