NGINX - OpenResty - 如何基于字符串反向代理对 2 个不同服务器的调用?

jed*_*lle 4 nginx lua openresty

我正在尝试配置 NGINX/OpenResty 以根据 SOAP 请求上存在的字符串将 SOAP 调用代理到 ​​2 个不同的服务器。

我能做什么:我能够根据 SOAP 客户端调用的路径将请求代理到 2 个不同的服务器:

location /pathA {
    proxy_pass http://www.ServerA.com/PathA/;
}
location /pathB {
    proxy_pass http://www.ServerB.com/PathB/;
}
Run Code Online (Sandbox Code Playgroud)

我不能做什么:

我无法根据请求的内容分离流量。我认为主要原因是我无法正确组装LUA脚本来提取信息并随后使用它来代理请求。

location / {
    conten_by_lua '
        ngx.req.read_body()
        local match = ngx.re.match(ngx.var.request_body,"STRING TO FIND")
        if match then
            proxy_pass http://www.ServerA.com/PathA/;
        else
            proxy_pass http://www.ServerB.com/PathB/;
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

我安装了 OpenResty 并且 LUA 工作正常。

我想我在某处读到如果请求不是 HTTP POSTngx.req.read_body()将不起作用。那是对的吗?

感谢您的帮助。

Iva*_*sky 5

你几乎自己做到了,我唯一会做的不同的事情就是使用rewrite_by_lua而不是content_by_lua

location / {
    set $proxy "";
    rewrite_by_lua '
        ngx.req.read_body()
        local match = ngx.re.match(ngx.var.request_body, "STRING TO FIND")
        if match then
            ngx.var.proxy = "www.ServerA.com"
        else
            ngx.var.proxy = "www.ServerB.com"
        end
    ';
    proxy_pass http://$proxy$uri;
}
Run Code Online (Sandbox Code Playgroud)

如果请求不是 HTTP POST 或具有空正文,ngx.req.read_body()将返回nil,因此最好添加额外的检查:

location / {
    set $proxy "";
    rewrite_by_lua '
        ngx.req.read_body()
        local body = ngx.var.request_body
        if (body) then
            local match = ngx.re.match(body, "STRING TO FIND")
            if match then
                ngx.var.proxy = "www.ServerA.com"
            else
                ngx.var.proxy = "www.ServerB.com"
            end
        else
            ngx.status = ngx.HTTP_NOT_FOUND
            ngx.exit(ngx.status)
        end
    ';
    proxy_pass http://$proxy$uri;
}
Run Code Online (Sandbox Code Playgroud)

您还可以限制允许的方法:

location / {
    limit_except POST { deny all; }
    ...
}
Run Code Online (Sandbox Code Playgroud)

还有一件事。使用此配置,如果您使用域名而不是 IP 地址指定后端,则需要resolver在配置中添加指令。您可以使用本地名称服务器(如果有),也可以使用外部名称服务器,例如 Google 公共 DNS (8.8.8.8) 或 ISP 为您提供的 DNS。