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 () не будет работать. Это правильно?

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

0
задан 21 December 2018 в 20:27
2 ответа

თქვენ ეს თითქმის გააკეთეთ, ერთადერთი, რასაც სხვანაირად გავაკეთებდი, არის 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 მისამართების ნაცვლად, თქვენს კონფიგურაციაში დაგჭირდებათ მოგვარების ინსტრუქცია. შეგიძლიათ გამოიყენოთ თქვენი ადგილობრივი სახელის სერვერი, თუ ეს გაქვთ, ან გამოიყენოთ ისეთი რამ, როგორიც არის Google public DNS (8.8.8.8) ან DNS, რომელიც თქვენთვის მოწოდებულია თქვენი ISP- ის მიერ.

1
ответ дан 4 December 2019 в 15:47

Вот фрагменты кода, которые я использовал в openresty, чтобы различать веб-хуки dev и prod в соответствии с опубликованным телом json:

server {
    listen 8080;
    resolver 114.114.114.114 8.8.8.8 valid=30s;

    location /webhook {
        limit_except POST { deny all; }

        set $proxy "";

        rewrite_by_lua_block {
            local devWebhook = "myservice.dev"   -- todo
            local prodWebhook = "mysevice.prod" -- todo

            function getFile(file_name)
                local f = assert(io.open(file_name, 'r'))
                local string = f:read("*all")
                f:close()
                return string
            end

            ngx.req.read_body()
            local data = ngx.req.get_body_data()
            if nil == data then
                local file_name = ngx.req.get_body_file()
                if file_name then
                    data = getFile(file_name)
                end
            end

            local json = require("cjson.safe")
            local t    = json.decode(data)
            if not (type(t) == "table" and t["msg"]) then
                ngx.exit(400)
            end               

            local msg = ngx.unescape_uri(t["msg"])
            if not (type(msg) == "string" and #msg > 0) then
                ngx.exit(400)
            end

            if string.find(msg, '"title":".*test product.*"') then
                ngx.var.proxy = devWebhook
            else
                ngx.var.proxy = prodWebhook
            end
        }

        proxy_pass http://$proxy$uri;
    }
}
0
ответ дан 25 November 2021 в 02:32

Теги

Похожие вопросы