【问题标题】:Nginx pass_proxy subdirectory without url decoding没有url解码的Nginx pass_proxy子目录
【发布时间】:2015-04-25 09:32:18
【问题描述】:

我需要编写一个 nginx 位置指令来代理对子目录的请求到另一台服务器保留 urlencoding删除子目录前缀

这是一个人为的例子——这样的请求:

http://1.2.3.4/api/save/http%3A%2F%2Fexample.com

应该通过

http://abcd.com/save/http%3A%2F%2Fexample.com

我尝试了几种不同的方法。这是其中的几个:

  1. 来自this SO question

     location /api/ {
         rewrite ^/api(/.*) $1 break;
         proxy_set_header   X-Real-IP        $remote_addr;
         proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
         proxy_set_header   Host             $host;
         proxy_pass http://abcd.com;
     }
    

但它会解码字符串,所以http://abcd.com 得到/save/http://example.com

  1. 来自another SO question

     location /api/ {
         proxy_set_header   X-Real-IP        $remote_addr;
         proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
         proxy_set_header   Host             $host;
         proxy_pass http://abcd.com;
     }
    

但它保留子目录,所以http://abcd.com 得到/api/save/http%3A%2F%2Fexample.com

需要的是中间的某个地方。谢谢!

UPD:这是 nginx 错误跟踪器中的 ticket

【问题讨论】:

  • 你可以试试 lua。但首先你不应该需要这个,根据 http 规范,这些 url 是相同的
  • 或者使用子域代替子目录
  • @AlexeyTen 在http://abcd.com 上运行的服务器正在以不同的方式处理这些请求,我无法控制它。你知道那个 http 规范摘录的链接吗?我找不到它
  • RFC 2616 第 3.2.3 节
  • @AlexeyTen 它说 “保留”和“不安全”集(参见 RFC 2396 [42])中的字符以外的字符等效于它们的“”%“HEX HEX”编码。 我不知道 RFC 2396 中的 [42] 是什么,但 RFC 中的第 2.2 节说这些字符是保留的 — ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

标签: nginx


【解决方案1】:

只要我们谈论前缀匹配 ^~ 或没有修饰符,你要做的事情就相当简单了

location /api/ {
  # if you don't want to pass /api/ add a trailing slash to the proxy_pass
  proxy_pass http://localhost:8080/;

  ...
}

而且一切都将不经解码就传递,你不必传递$uri

此外,当您使用代理通行证时,您还应该设置这些标头

# pass headers and body along
proxy_pass_request_headers on;
proxy_pass_request_body on;

# set some headers to make sure the reverse proxy is passing along everything necessary
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

【讨论】:

  • "everything will pass" :是的,直到你用变量替换 localhost upstream。
  • 允许踢自己。很简单! facepalms ?‍♀️ 我实际上遇到了正好相反的问题——确保完整路径通过。谁会猜到斜杠会产生如此大的不同...谢谢,您的回答为我节省了数小时的调试时间!
【解决方案2】:

但是没有简单的方法来解决这个 nginx 行为。 nginx trac 中有一些错误,你可以添加你的。 trac.nginx.org/nginx/…。所以,我认为最简单的方法是拥有子域。 – 阿列克谢十 2015 年 2 月 24 日 14:49

https://trac.nginx.org/nginx/ticket/727

如果你想让 nginx 做一些自定义的事情,你可以使用带有变量的 ​proxy_pass(和 $request_uri 变量,它包含客户端发送的原始未转义请求 URI)。在这种情况下,您有责任进行正确的 URI 转换。请注意,这很容易导致安全问题,应小心操作。

接受挑战!

    location /api/ {
        rewrite ^ $request_uri;
        rewrite ^/api/(.*) $1 break;
        return 400;
        proxy_pass http://127.0.0.1:82/$uri;
    }

就是这样,伙计们!


这是完整的证明。

nginx/1.2.1的配置文件:

server {
    listen 81;
    #first, the solution
    location /api/ {
        rewrite ^ $request_uri;
        rewrite ^/api/(.*) $1 break;
        return 400; #if the second rewrite won't match
        proxy_pass http://127.0.0.1:82/$uri;
    }
    #next, a few control groups
    location /dec/ {
        proxy_pass http://127.0.0.1:82/;
    }
    location /mec/ {
        rewrite ^/mec(/.*) $1 break;
        proxy_pass http://127.0.0.1:82;
    }
    location /nod/ {
        proxy_pass http://127.0.0.1:82;
    }
}

server {
    listen 82;
    return 200 $request_uri\n;
}

以下是针对每个位置运行查询的结果:

% echo localhost:81/{api,dec,mec,nod}/save/http%3A%2F%2Fexample.com | xargs -n1 curl
/save/http%3A%2F%2Fexample.com
/save/http:/example.com
/save/http:/example.com
/nod/save/http%3A%2F%2Fexample.com
%

请注意,拥有额外的 return 400; 非常重要 - 否则,您可能会遇到安全问题(通过 //api 访问文件等),正如 Maxim 在您的 trac 票证中简要提到的那样。


附:如果您认为将重写引擎用作有限状态自动机非常酷,您可能还想查看我的http://mdoc.su/ 项目或fork it github

【讨论】:

  • 说真的......谢谢你。真正的哇,它实际上按预期工作。鉴于与现有规则的相似性,神奇之处显然在于 $request_uri 捕获。
  • 为了避免the rewritten URI has a zero length错误,我使用了rewrite ^ $request_uri;重写 ^/api(/.*) $1 break;返回 400; proxy_pass 127.0.0.1:82$uri;
  • 答案应该被接受。非常感谢您在事情突然开始变得奇怪时提供帮助!
  • return 200 $request_uri\n;
  • 你拯救了我的一天。谢谢! :-)
猜你喜欢
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 2012-10-13
  • 2017-06-17
相关资源
最近更新 更多