Open membphis opened 2 years ago
@membphis
Issue description https://www.processon.com/view/link/626a5b656376891e1c158aad At present, the configuration items of the nginx file of apisix and the processing flow of APISIX are shown in the following figure
In the calling phase of the ``http_access_phase```` method, the relevant upstream id will be obtained to split the sent data. And in the init.lua method, the following code will appear
init.lua
function _M.http_access_phase()
local ngx_ctx = ngx.ctx
if not verify_tls_client(ngx_ctx.api_ctx) then
return core.response.exit(400)
end
-- always fetch table from the table pool, we don't need a reused api_ctx
local api_ctx = core.tablepool.fetch("api_ctx", 0, 32)
ngx_ctx.api_ctx = api_ctx
local up_id = route.value.upstream_id
-- used for the traffic-split plugin
if api_ctx.upstream_id then
up_id = api_ctx.upstream_id
end
if up_id then
> local upstream = get_upstream_by_id(up_id)
api_ctx.matched_upstream = upstream
end
local function get_upstream_by_id(up_id)
local upstreams = core.config.fetch_created_obj("/upstreams")
if upstreams then
local upstream = upstreams:get(tostring(up_id))
if not upstream then
core.log.error("failed to find upstream by id: " .. up_id)
if is_http then
return core.response.exit(502)
end
return ngx_exit(1)
end
if upstream.has_domain then
local err
upstream, err = parse_domain_in_up(upstream)
if err then
core.log.error("failed to get resolved upstream: ", err)
if is_http then
return core.response.exit(500)
end
return ngx_exit(1)
end
end
core.log.info("parsed upstream: ", core.json.delay_encode(upstream, true))
return upstream.dns_value or upstream.value
end
end
To understand how router.lua is called based on upstream_id, I traced the following code. In the request process of Route's admin api:
local function filter(route)
route.orig_modifiedIndex = route.modifiedIndex
route.update_count = 0
route.has_domain = false
if not route.value then
return
end
if route.value.host then
route.value.host = str_lower(route.value.host)
elseif route.value.hosts then
for i, v in ipairs(route.value.hosts) do
route.value.hosts[i] = str_lower(v)
end
end
apisix_upstream.filter_upstream(route.value.upstream, route)
core.log.info("filter route: ", core.json.delay_encode(route, true))
To sum up, I think that consumer.lua should do some attribute extraction before calling the apisix_upstream.filter_upstream
method and then execute the filter. So based on this idea, I decided to follow up the related call link of route call /upstream
I would like to know suppose now that I want to configure a set of admin api as shown below, how should I do the relevant verification on the consumer side to complete the connectivity test of calling /upstream
from the route /consumer
?
location /apisix/admin {
set $upstream_scheme 'http';
set $upstream_host $http_host;
set $upstream_uri '';
allow 127.0.0.0/24;
deny all;
content_by_lua_block {
apisix.http_admin()
}
}
Hi @complone , from your trace path, I think you have missed the key point, APISIX merge the consumer's plugins and route's plugins is here: https://github.com/apache/apisix/blob/4afc8a7fbf82d4311504abd00f08156a806e5b40/apisix/plugin.lua#L491-L513
@tzssangglass
I understand that I should define the relevant plugin_config_id in shcema_def.lua
, and then set the relevant plugin_config_id in consumer.lua#plugin_consumer
shcema_def.lua
_M.consumer = {
type = "object",
properties = {
username = {
type = "string", minLength = 1, maxLength = rule_name_def.maxLength,
pattern = [[^[a-zA-Z0-9_]+$]]
},
> id = id_schema,
plugins = plugins_schema,
labels = labels_def,
create_time = timestamp_def,
update_time = timestamp_def,
desc = desc_def,
},
required = {"username"},
}
consumer.lua
local function plugin_consumer()
local plugins = {}
if consumers.values == nil then
return plugins
end
for _, consumer in ipairs(consumers.values) do
if type(consumer) ~= "table" then
goto CONTINUE
end
for name, config in pairs(consumer.value.plugins or {}) do
local plugin_obj = plugin.get(name)
if plugin_obj and plugin_obj.type == "auth" then
if not plugins[name] then
plugins[name] = {
nodes = {},
conf_version = consumers.conf_version
}
end
local new_consumer = core.table.clone(consumer.value)
-- Note: the id here is the key of consumer data, which
-- is 'username' field in admin
> new_consumer.id = consumer.value.id
new_consumer.consumer_name = new_consumer.id
new_consumer.auth_conf = config
core.log.info("consumer:", core.json.delay_encode(new_consumer))
core.table.insert(plugins[name].nodes, new_consumer)
end
end
::CONTINUE::
end
return plugins
end
I will start testing the relevant request processing link in the near future
Issue description
Now, the
router
object supports theplugin_config_id
, here is the doc link: https://github.com/apache/apisix/blob/master/docs/en/latest/admin-api.md#routeAnd I think we need to support
plugin_config_id
forconsumer
object.What do you think?
Environment