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.

Revisions

  1. @br41n10 br41n10 created this gist Apr 12, 2024.
    106 changes: 106 additions & 0 deletions dynamic_uri_upstream.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,106 @@
    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