如何使用 nginx 通过 proxy_pass 转发查询字符串参数?
Posted
技术标签:
【中文标题】如何使用 nginx 通过 proxy_pass 转发查询字符串参数?【英文标题】:How can query string parameters be forwarded through a proxy_pass with nginx? 【发布时间】:2011-12-29 03:55:37 【问题描述】:upstream apache
server 127.0.0.1:8080;
server
location ~* ^/service/(.*)$
proxy_pass http://apache/$1;
proxy_redirect off;
上面的sn-p会将url包含字符串“service”的请求重定向到另一个服务器,但不包含查询参数。
【问题讨论】:
【参考方案1】:添加了 $request_uri: proxy_pass http://apache/$request_uri;
【讨论】:
【参考方案2】:要在没有查询字符串的情况下重定向,请在侦听端口行下的服务器块中添加以下行:
if ($uri ~ .*.containingString$)
return 301 https://$host/$uri/;
使用查询字符串:
if ($uri ~ .*.containingString$)
return 301 https://$host/$uri/?$query_string;
【讨论】:
nginx 文档明确指出尽可能避免使用if
。在这种情况下,使用location
的解决方案可能是正确的,如另一个答案所示。
不管怎样,再一个解决方案,即使它有缺点更好【参考方案3】:
github 要点https://gist.github.com/anjia0532/da4a17f848468de5a374c860b17607e7
#set $token "?"; # deprecated
set $token ""; # declar token is ""(empty str) for original request without args,because $is_args concat any var will be `?`
if ($is_args) # if the request has args update token to "&"
set $token "&";
location /test
set $args "$args$tokenk1=v1&k2=v2"; # update original append custom params with $token
# if no args $is_args is empty str,else it's "?"
# http is scheme
# service is upstream server
#proxy_pass http://service/$uri$is_args$args; # deprecated remove `/`
proxy_pass http://service$uri$is_args$args; # proxy pass
#http://localhost/test?foo=bar ==> http://service/test?foo=bar&k1=v1&k2=v2
#http://localhost/test/ ==> http://service/test?k1=v1&k2=v2
【讨论】:
【参考方案4】:来自proxy_pass 文档:
一种特殊情况是在 proxy_pass 语句中使用变量:请求的 URL 未被使用,您完全负责自己构建目标 URL。
由于您在目标中使用 $1,因此 nginx 依赖于您准确地告诉它要传递的内容。您可以通过两种方式解决此问题。首先,用 proxy_pass 剥离 uri 的开头很简单:
location /service/
# Note the trailing slash on the proxy_pass.
# It tells nginx to replace /service/ with / when passing the request.
proxy_pass http://apache/;
或者,如果您想使用正则表达式位置,只需包含参数:
location ~* ^/service/(.*)
proxy_pass http://apache/$1$is_args$args;
【讨论】:
我不相信你能做到后者。我试过了,nginx 向我抱怨。 如何投诉?我刚刚在 nginx 1.3.4 上对其进行了测试,对我来说效果很好。 嗯..我现在不记得了:(但我觉得它可能与“〜*”有关。但是,我刚刚检查过,我有nginx 1.2.3(通过自制)。也许就是这样? “proxy_redirect default”不能与带有变量的“proxy_pass”指令一起使用 必须使用重写location /service/ rewrite ^\/service\/(.*) /$1 break; proxy_pass http://apache;
【参考方案5】:
您必须使用 rewrite 来使用 proxy_pass 传递参数 这是我为 angularjs 应用程序部署到 s3 所做的示例
S3 Static Website Hosting Route All Paths to Index.html
根据您的需要采用类似于
location /service/
rewrite ^\/service\/(.*) /$1 break;
proxy_pass http://apache;
如果你想结束http://127.0.0.1:8080/query/params/
如果你想结束http://127.0.0.1:8080/service/query/params/ 你需要类似的东西
location /service/
rewrite ^\/(.*) /$1 break;
proxy_pass http://apache;
【讨论】:
这看起来可以很好地处理路径参数 (/path/params
) 但不能很好地处理查询参数 (?query=params
)?
啊不,我错了,应该自动添加查询参数(它们在我的测试中)。【参考方案6】:
我修改了@kolbyjack 代码以使其适用于
http://website1/service
http://website1/service/
带参数
location ~ ^/service/?(.*)
return 301 http://service_url/$1$is_args$args;
【讨论】:
请记住,这将使服务器在重定向之前向客户端返回 301 响应。上面的proxy_pass
指令在服务器端进行重定向。
如果您的查询参数包含 URL(%) 编码字符,这将中断。请改用安德鲁的答案。
这个答案与反向代理无关。例如,如果 service_url 不能直接从 Internet 访问(这很可能在反向代理场景中),它将完全失败。此外,它告诉客户端它下次应该直接使用重定向 URL(301 永久移动),这在这种情况下也可能不需要。【参考方案7】:
我使用了 kolbyjack 第二种方法的略微修改版本,使用 ~
而不是 ~*
。
location ~ ^/service/
proxy_pass http://apache/$uri$is_args$args;
【讨论】:
以上是关于如何使用 nginx 通过 proxy_pass 转发查询字符串参数?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 nginx proxy_pass 保留请求 url
如何解决 Nginx “proxy_pass 502 Bad Gateway”错误
nginx proxy_pass基于请求方法是POST,PUT还是DELETE