最初我有一个这样的conf:
location /some/path/ {
proxy_pass http://other.host/foo/;
}
并且对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/;
}
但是我发现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;
}
但是不包含任何查询参数,因此我再次进行了更新
location ~ ^/some/path/(.*) {
resolver 1.2.3.4;
set $proxy_root "other.host/foo"
proxy_pass http://$proxy_root/$1?$args;
}
这有点用,但这意味着有一个?在每个目标地址中,当只有一些传入的请求实际上有一个?query节...
我想我可以做一些进一步的字符串操作,但是感觉有点多。有没有像我最初那样简单的方法来proxy_pass,但是将proxy target作为变量来强制重新解析?
代替使用位置匹配器,另一种选择是使用$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;
}
最后,将余数连接:
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;
}
关于发生这种情况的原因,根据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; }
在这种情况下,如果在指令中指定了URI,它将照原样传递到服务器,从而替换原始请求URI。
这里就是这种情况,因为您的proxy_pass指令参数中有$ proxy_root。