【问题标题】:nginx - Proxy to a different backend based on query paramnginx - 根据查询参数代理到不同的后端
【发布时间】:2021-06-23 16:48:11
【问题描述】:

我有一个案例,我想根据查询参数的存在将特定调用代理到不同的后端。以下是我开始的内容

location ~ ^/abc/xyz/?$ {
    proxy_pass $backend_url;
 }

我想做的是检查查询参数 foo(或者甚至只是该字符串在任何地方的存在)。所以我想我可以做到这一点

location ~ ^/abc/xyz/?$ {
    set $backend_url "somelocation"

    if ($request_url ~ .*foo.*) {
       set $backend_url "someotherlocation"
       proxy_pass $backend_url
    }
    proxy_pass $backend_url;
 }

但这似乎并没有真正代理到新位置。我的代码有什么问题,还是整个方法都错了?

【问题讨论】:

    标签: nginx


    【解决方案1】:

    我不知道你为什么要使用两个 proxy_pass 指令,这个块应该按照你描述的逻辑来做:

    location ~ ^/abc/xyz/?$ {
        set $backend_url "somelocation";
        if ($request_url ~ \?(.*&)?foo(=|&|$)) {
           set $backend_url "otherlocation";
        }
        proxy_pass $backend_url;
     }
    

    我稍微修改了您的正则表达式,以仅匹配 foo 是查询参数名称而不是查询参数值(或其部分)的请求 URL。但是我宁愿为此目的使用map 指令(地图块应放置在外部服务器块):

    map $arg_foo $backend_url {
        ""      somelocation;  # if the value is empty
        default otherlocation; # otherwise
    }
    
    server {
        ...
        location ~ ^/abc/xyz/?$ {
            proxy_pass $backend_url;
        }
    }
    

    请注意,您可能需要定义一个 resolver 才能使此配置正常工作(有关此的一些附加信息可以找到 here)。

    【讨论】:

    • 谢谢!我把 proxy_pass 放在那里,因为在代码的真实版本中,有更多的东西修改了 backend_url(一些 Lua 模块)。但它可能不需要。
    • 回复:您的第二个建议 - arg_foo 是否做了一些特殊的事情(即提取一个名为 foo 的查询参数)还是我需要一些东西来填充它?
    • 是的,你是对的,$arg_name 是根据查询参数提取的特殊 nginx 变量(here 是描述)。关于您的第一条评论 - 实际上每个 if 块都是一个虚拟嵌套位置,它试图从上一级继承所有可用的指令(有时甚至包括那些通常不被继承的指令),所以它没有太大的区别。
    • if 指令行为有时非常不清楚。 lua-nginx-module 和 OpenResty nginx 分支的作者 Yichun Zhang 对 if 位置的工作原理做了一个很好的解释:How nginx "location if" works
    猜你喜欢
    • 2021-11-30
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2019-10-11
    • 2013-03-18
    • 2016-05-28
    • 2019-03-04
    • 2021-03-02
    相关资源
    最近更新 更多