带有变量的 Nginx proxy_pass - 完整路径

Taa*_*Taa 11 nginx proxypass

最初我有一个这样的conf:

location /some/path/ {
  proxy_pass       http://other.host/foo/;
}
Run Code Online (Sandbox Code Playgroud)

并且请求http://my.domain/some/path/bar将被代理到http://other.host/foo/bar

我开始在 proxy_pass 中使用变量来强制 nginx 重新解析 DNS:

location /some/path/ {
  resolver        1.2.3.4;
  set $proxy_root  "other.host/foo"
  proxy_pass       http://$proxy_root/;
}
Run Code Online (Sandbox Code Playgroud)

但是我发现 uri 路径的其余部分不再被附加,所以现在请求http://my.domain/some/path/bar将被代理到简单的http://other.host/foo/.

所以我把它改成了正则表达式

location ~ ^/some/path/(.*) {
  resolver        1.2.3.4;
  set $proxy_root  "other.host/foo"
  proxy_pass       http://$proxy_root/$1;
}
Run Code Online (Sandbox Code Playgroud)

但这不包括任何查询参数,所以我再次更新

location ~ ^/some/path/(.*) {
  resolver        1.2.3.4;
  set $proxy_root  "other.host/foo"
  proxy_pass       http://$proxy_root/$1?$args;
}
Run Code Online (Sandbox Code Playgroud)

这有点工作,但这意味着有一个 ? 在每个目标地址中,当只有一些传入请求实际上具有 ?query 部分时...

我想我可以做一些进一步的字符串操作,但这感觉有点多。有没有像我最初做的那样更简单的 proxy_pass 方法,但是将代理目标作为变量来强制重新解析?

小智 5

除了使用位置匹配器,另一种选择是使用$request_uri和匹配您要维护的部件。$request_uri包含完整的 URI,包括查询参数 ( http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri )。

由于location块匹配/some/path/,使用正则表达式获得余数:

  if ($request_uri ~* "/some/path(/.*$)")
      set  $path_remainder  $1;
  }
Run Code Online (Sandbox Code Playgroud)

最后,连接余数:

location /some/path/ {
  resolver        1.2.3.4;
  set $proxy_root  "other.host/foo";
  if ($request_uri ~* "/some/path(/.*$)") {
      set  $path_remainder  $1;
  }
  proxy_pass       http://$proxy_root$path_remainder;
}
Run Code Online (Sandbox Code Playgroud)

至于为什么会发生这种情况,根据http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

在某些情况下,无法确定要替换的请求 URI 部分

其中一个案例是

在 proxy_pass 中使用变量时:

location /name/ {
    proxy_pass http://127.0.0.1$request_uri; 
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果在指令中指定了 URI,它将按原样传递给服务器,替换原始请求 URI。

这是这种情况,因为您的 proxy_pass 指令参数中有 $proxy_root 。