Назад | Перейти на главную страницу

NGINX - OpenResty - Как отменить прокси-вызов 2 разных серверов на основе строки?

Я пытаюсь настроить NGINX / OpenResty для прокси-вызовов SOAP на 2 разных сервера на основе строки, присутствующей в запросе SOAP.

Что я могу сделать: я могу отправлять запросы прокси на 2 разных сервера в зависимости от пути, который вызывает клиент SOAP:

location /pathA {
    proxy_pass http://www.ServerA.com/PathA/;
}
location /pathB {
    proxy_pass http://www.ServerB.com/PathB/;
}

Что я не могу сделать:

Я не могу разделить трафик по содержанию запроса. Основная причина, по которой я считаю, заключается в том, что я не могу правильно собрать сценарий 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/;

как я могу этого добиться?

Я установил OpenResty, и LUA работает нормально.

Кажется, я где-то читал, что если запрос не является HTTP POST ngx.req.read_body() не будет работать. Это правильно?

Спасибо за помощь.

Вы почти сделали это сами, единственное, что я бы сделал иначе - это использовать 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;
}

Если запрос не является 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;
}

Вы также можете ограничить разрешенные методы:

location / {
    limit_except POST { deny all; }
    ...
}

Еще кое-что. В этой конфигурации, если вы укажете свои серверные ВМ с доменными именами вместо IP-адресов, вам понадобится resolver директиву в вашем config. Вы можете использовать свой локальный сервер имен, если он у вас есть, или использовать что-то внешнее, например общедоступный DNS Google (8.8.8.8) или DNS, предоставленный вам вашим интернет-провайдером.