apisix icon indicating copy to clipboard operation
apisix copied to clipboard

help request: What is the best way to dynamically route a cluster by token in customer plugin?

Open xBoo opened this issue 1 year ago • 3 comments

Description

i got tenantid in jwt token, and i want to use this id to route the cluster, how can i do it ?

local jwt_obj = jwt:verify(conf.jwt_secret, token)
    if jwt_obj.valid and jwt_obj.verified then
        local tid = jwt_obj.payload.tid
        if tid ~= nil then
            local red, err = redis.new(conf)
            if not red then
                return 502, err
            end

            local domain, redis_err = red:get("tid-" .. tid)
            if not domain or domain == nil or (type(domain) == "userdata" and tostring(domain) == "userdata: NULL") then
                return 502, redis_err
            else
               -- Here I do not know,how can i set the  cluster domain?use the upstream id is the best way?
               --like this?  ctx.upstream_id = "512895159801742021"
                core.request.set_header(ctx, "x-cluster", domain)
            end
        else
            -- todo: add no token handle
            core.log.warn("tid is nil, set default cluster")
        end
    else
        core.log.warn("jwt valid error:" .. core.json.encode(jwt_obj))
        return 502, jwt_obj.reason
    end

Environment

  • APISIX version (run 3.9.0):
  • Operating system (run uname -a):
  • OpenResty / Nginx version (run openresty -V or nginx -V):
  • etcd version, if relevant (run curl http://127.0.0.1:9090/v1/server_info):
  • APISIX Dashboard version, if relevant:
  • Plugin runner version, for issues related to plugin runners:
  • LuaRocks version, for installation issues (run luarocks --version):

xBoo avatar Jun 07 '24 09:06 xBoo

APISIX doesn't support this.

shreemaan-abhishek avatar Jun 13 '24 04:06 shreemaan-abhishek

I found an implementation, which is done through the following code: dymainc_uri_upstream.lua

 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)

But I don't think it's a best practice because many parameters become fixed values and cannot be dynamically configured. I found that it can also be achieved by setting the upstream_id, but I don't know what the risks are.

xBoo avatar Jun 17 '24 06:06 xBoo

APISIX doesn't support this. Dynamic routing based on user (token) information is crucial in a multi-cluster mode, and I hope APISIX can implement this.

xBoo avatar Jun 17 '24 06:06 xBoo

You can do this by writing custom plugins. If there is still a problem, please open it again.

Baoyuantop avatar May 15 '25 14:05 Baoyuantop