Created
April 12, 2024 04:50
-
-
Save br41n10/e2d378c7a04d4861b2f0cbf4d2476d71 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
Note: in nginx, this can be done very simple