Skip to content

Instantly share code, notes, and snippets.

@busyboy77
Forked from br41n10/dynamic_uri_upstream.lua
Created August 11, 2025 05:42
Show Gist options
  • Save busyboy77/301ee303f8137061b0b70fafe36f63f3 to your computer and use it in GitHub Desktop.
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.
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