我在nginx后面运行了一个应用程序。为了允许客户在相同的主机名下添加自己的工具,我们使用location
这样的类型:
location /some-extension {
rewrite ^/(.*) /$1 break;
proxy_pass http://customers-app/$1/$args;
}
现在,我想使这个动态,以便给定的客户可以创建零个或多个这样的位置。由于应用程序与Docker一起部署,因此我无法手动编辑nginx配置。
Nginx是用perl和lua支持编译的,所以我在考虑这样的事情:
path1 url1 path-2 url2 ... pathn urln
表单上的环境变量来配置外部工具。location
配置中,将请求网址的第一个路径段与环境变量匹配,并将proxy_pass
与相应的网址匹配(如果找到)。到目前为止,这就是我所拥有的:
location / {
content_by_lua '
local target_path = ngx.var.uri;
local name = nil
if target_path:len() > 0 then
startAt = target_path:find("/") + 1
endAt = target_path:find("/", startAt) - 1
name = target_path:sub(startAt,endAt)
ngx.say(name)
end
if name then
local custom_proxies = os.getenv("CUSTOM_PROXIES");
inString = custom_proxies:find("another ")
if not inString then
ngx.say("not in string")
else
startAt = custom_proxies:find(" ", inString + 1) + 1
endAt = custom_proxies:find(" ", startAt)
url = custom_proxies:sub(startAt,endAt)
ngx.say(url)
end
end
';
}
我知道我不应该使用content_by_lua
,但它似乎有点工作。问题是我如何才能将proxy_pass
发送到指定的网址?
答案 0 :(得分:0)
我通过以下方式解决了这个问题:
环境变量应该是以空格分隔的名称和URL列表; key http://example.com/app1 key2 http://acme.com
。
Lua脚本将环境变量读入table
,其中key
为关键,后面的URL为值。
nginx location
块将处理请求并使用Lua脚本查找要代理的模块。
函数将接受请求路径并从中找到密钥,然后在表中查找URL。
这是脚本:
local custom_proxies = os.getenv("CUSTOM_PROXIES")
local custom_modules = {}
local cutFrom = 0
local cutTo = 0
while cutTo < custom_proxies:len() do
cutFrom = cutTo
cutTo = custom_proxies:find(" ", cutFrom + 1)
local name = custom_proxies:sub(cutFrom, cutTo - 1)
cutFrom = cutTo + 1
cutTo = custom_proxies:find(" ", cutFrom)
if not cutTo then
cutTo = custom_proxies:len() + 1
end
local url = custom_proxies:sub(cutFrom, cutTo - 1)
custom_modules[name] = url
cutTo = cutTo + 1
end
function custom_modules.get_url(target_path)
local name = nil
local startAt = target_path:find("/", 6) + 1
local endAt = target_path:find("/", startAt)
if not endAt then
endAt = target_path:len()
else
endAt = endAt - 1
end
name = target_path:sub(startAt,endAt)
if name then
return custom_modules[name]
else
ngx.log(ngx.STDERR, "Not able to deduct module name from URI")
return ""
end
end
return custom_modules
这里是nginx location
:
location /custom/ {
set_by_lua $redirect_to '
local custom_modules = require "read_proxies"
local url = custom_modules.get_url(ngx.var.uri)
if not url then
ngx.log(ngx.STDERR, "Not a known custom module.")
end
return url
';
if ($redirect_to = '') {
return 404 'Unknown custom module.';
}
rewrite ^/custom/\w+/(.*) /$1 break;
proxy_pass $redirect_to$1?$args;
}
我们的想法是/custom/foobar/path/to/something?page=2
之类的请求会使用foobar
作为查找网址的密钥,并使用其余路径和参数proxy_pass
来查找网址。