-
-
Save busyboy77/301ee303f8137061b0b70fafe36f63f3 to your computer and use it in GitHub Desktop.
An Apisix plugin to dynamically set upstream host:port based on URI, or Header or whatever. Very basic implementation, modify on your needs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local upstream = require("apisix.upstream") | |
local core = require("apisix.core") | |
local ipmatcher = require("resty.ipmatcher") | |
local ngx = ngx | |
local schema = { | |
type = "object", | |
properties = { | |
}, | |
additionalProperties = true, | |
} | |
local _M = { | |
version = 0.1, | |
priority = 80, | |
name = 'dynamic_uri_upstream', | |
schema = schema, | |
} | |
local function parse_domain(host) | |
local ip = "" | |
if not ipmatcher.parse_ipv4(host) and not ipmatcher.parse_ipv6(host) | |
then | |
local ip, err = core.resolver.parse_domain(host) | |
if ip then | |
return ip | |
end | |
if err then | |
core.log.error("dns resolver domain: ", host, " error: ", err) | |
end | |
end | |
return host | |
end | |
function _M.check_schema(conf) | |
return core.schema.check(schema, conf) | |
end | |
function _M.access(conf, ctx) | |
-- Get the request URI | |
local uri = ngx.var.uri | |
local args = ngx.var.args | |
-- get upstream hostport and path based on uri | |
local upstream_hostport, path = string.match(uri, "^/proxy/([^/]+)/?(.*)") -- change here on your needs !!!!! | |
if not path then | |
path = "" | |
end | |
local upstream_host, upstream_port = string.match(upstream_hostport, "([^:]+):?(%d*)") | |
if upstream_port == "" then | |
upstream_port = "80" | |
end | |
upstream_port = tonumber(upstream_port) | |
-- core.log.warn("hostport: ", upstream_hostport) | |
-- core.log.warn("path: ", path) | |
-- set path | |
ngx.req.set_uri("/" .. path) | |
-- set upstream | |
-- some params can be set from existing upstream config | |
-- or can be set by plugin conf | |
local up_conf = { | |
timeout = { | |
connect = 6, | |
send = 300, | |
read = 300 | |
}, | |
scheme = "http", | |
type = "roundrobin", | |
pass_host = "pass", | |
keepalive_pool = { | |
idle_timeout = 60, | |
requests = 1000, | |
size = 320 | |
}, | |
hash_on = "vars", | |
nodes = { | |
{ | |
priority = 0, | |
port = upstream_port, | |
host = parse_domain(upstream_host), | |
weight = 1 | |
} | |
} | |
} | |
local ok, err = upstream.check_schema(up_conf) | |
if not ok then | |
core.log.error("failed to validate generated upstream: ", err) | |
return 500, err | |
end | |
local matched_route = ctx.matched_route | |
up_conf.parent = matched_route | |
local upstream_key = up_conf.type .. "#route_" .. matched_route.value.id | |
core.log.info("upstream_key: ", upstream_key) | |
upstream.set(ctx, upstream_key, ctx.conf_version, up_conf) | |
end | |
return _M |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment