Я пытаюсь настроить 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 მისამართების ნაცვლად, თქვენს კონფიგურაციაში დაგჭირდებათ მოგვარების
ინსტრუქცია. შეგიძლიათ გამოიყენოთ თქვენი ადგილობრივი სახელის სერვერი, თუ ეს გაქვთ, ან გამოიყენოთ ისეთი რამ, როგორიც არის Google public DNS (8.8.8.8) ან DNS, რომელიც თქვენთვის მოწოდებულია თქვენი ISP- ის მიერ.
Вот фрагменты кода, которые я использовал в 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;
}
}