在 nginx 代理中禁用 URL 解码

在 nginx 代理中禁用 URL 解码

当我浏览此 URL 时,http://localhost:8080/foo/%5B-%5D服务器(nc -l 8080)按原样接收它:

GET /foo/%5B-%5D HTTP/1.1

但是当我通过 nginx (1.1.19)代理该应用程序时:

location /foo {
        proxy_pass    http://localhost:8080/foo;
}

通过 nginx 端口路由的相同请求将使用解码的路径进行转发:

GET /foo/[-] HTTP/1.1

GET 路径中解码的方括号导致目标服务器出现错误(HTTP 状态 400-路径中有非法字符...) 到达时它们尚未逃脱。

有没有办法禁用 URL 解码或将其重新编码,以便目标服务器在通过 nginx 路由时获得完全相同的路径?一些巧妙的 URL 重写规则?

答案1

引用瓦伦丁·V·巴尔捷涅夫(谁应该获得这个答案的全部荣誉):

引自文档

  • 如果指定了 proxy_pass带有 URI,在向服务器传递请求时,规范化与位置匹配的请求 URI 将被指令中指定的 URI 替换

  • 如果proxy_pass指定无 URI,请求 URI 以客户端处理原始请求时发送的相同形式传递给服务器

您的情况下的正确配置是:

location /foo {
   proxy_pass http://localhost:8080;
}

答案2

请注意,URL 解码(通常称为$uri“正常化”在 nginx 的文档中,发生在后端 IFF 之前:

  • 任何 URI 都是在proxy_pass其自身内指定的,即使只是一个尾随斜杠,

  • 或者,URI 在处理过程中发生变化,例如通过rewrite


这两种情况都明确记录在http://nginx.org/r/proxy_pass(重点是我的):

  • 如果proxy_pass指定了指令使用 URI,那么当请求传递到服务器时,规范化与位置匹配的请求 URI 将被指令中指定的 URI 替换

  • 如果proxy_pass指定没有 URI,请求 URI 被传递到服务器与客户发送的表单相同当原始请求被处理时,或者完整的规范化请求 URI 已传递什么时候处理已更改 URI


解决方案要么是像原作者的情况一样省略 URI,要么是使用一个巧妙的rewrite规则:

# map `/foo` to `/foo`:
location /foo {
    proxy_pass  http://localhost:8080;  # no URI -- not even just a slash
}

# map `/foo` to `/bar`:
location /foo {
    rewrite  ^  $request_uri;            # get original URI
    rewrite  ^/foo(/.*)  /bar$1  break;  # drop /foo, put /bar
    return 400;   # if the second rewrite won't match
    proxy_pass    http://localhost:8080$uri;
}

你可以在 Stack Overflow 的相关回答中查看,包括对照组。

相关内容