Skip to content

Commit

Permalink
feat: support _meta.pre_function to execute custom logic before execu…
Browse files Browse the repository at this point in the history
…tion of each phase (#11793)
  • Loading branch information
Revolyssup authored Jan 28, 2025
1 parent 0cb7d9a commit c2324a5
Show file tree
Hide file tree
Showing 5 changed files with 380 additions and 8 deletions.
40 changes: 36 additions & 4 deletions apisix/plugin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ local type = type
local local_plugins = core.table.new(32, 0)
local tostring = tostring
local error = error
-- make linter happy to avoid error: getting the Lua global "load"
-- luacheck: globals load, ignore lua_load
local lua_load = load
local is_http = ngx.config.subsystem == "http"
local local_plugins_hash = core.table.new(0, 32)
local stream_local_plugins = core.table.new(32, 0)
Expand All @@ -49,6 +52,9 @@ local merged_stream_route = core.lrucache.new({
local expr_lrucache = core.lrucache.new({
ttl = 300, count = 512
})
local meta_pre_func_load_lrucache = core.lrucache.new({
ttl = 300, count = 512
})
local local_conf
local check_plugin_metadata

Expand Down Expand Up @@ -906,10 +912,23 @@ local function check_single_plugin_schema(name, plugin_conf, schema_type, skip_d
.. name .. " err: " .. err
end

if plugin_conf._meta and plugin_conf._meta.filter then
ok, err = expr.new(plugin_conf._meta.filter)
if not ok then
return nil, "failed to validate the 'vars' expression: " .. err
if plugin_conf._meta then
if plugin_conf._meta.filter then
ok, err = expr.new(plugin_conf._meta.filter)
if not ok then
return nil, "failed to validate the 'vars' expression: " .. err
end
end

if plugin_conf._meta.pre_function then
local pre_function, err = meta_pre_func_load_lrucache(plugin_conf._meta.pre_function
, "",
lua_load,
plugin_conf._meta.pre_function, "meta pre_function")
if not pre_function then
return nil, "failed to load _meta.pre_function in plugin " .. name .. ": "
.. err
end
end
end
end
Expand Down Expand Up @@ -1130,6 +1149,17 @@ function _M.stream_plugin_checker(item, in_cp)
return true
end

local function run_meta_pre_function(conf, api_ctx, name)
if conf._meta and conf._meta.pre_function then
local _, pre_function = pcall(meta_pre_func_load_lrucache(conf._meta.pre_function, "",
lua_load,
conf._meta.pre_function, "meta pre_function"))
local ok, err = pcall(pre_function, conf, api_ctx)
if not ok then
core.log.error("pre_function execution for plugin ", name, " failed: ", err)
end
end
end

function _M.run_plugin(phase, plugins, api_ctx)
local plugin_run = false
Expand Down Expand Up @@ -1169,6 +1199,7 @@ function _M.run_plugin(phase, plugins, api_ctx)
goto CONTINUE
end

run_meta_pre_function(conf, api_ctx, plugins[i]["name"])
plugin_run = true
api_ctx._plugin_name = plugins[i]["name"]
local code, body = phase_func(conf, api_ctx)
Expand Down Expand Up @@ -1207,6 +1238,7 @@ function _M.run_plugin(phase, plugins, api_ctx)
local conf = plugins[i + 1]
if phase_func and meta_filter(api_ctx, plugins[i]["name"], conf) then
plugin_run = true
run_meta_pre_function(conf, api_ctx, plugins[i]["name"])
api_ctx._plugin_name = plugins[i]["name"]
phase_func(conf, api_ctx)
api_ctx._plugin_name = nil
Expand Down
8 changes: 8 additions & 0 deletions apisix/plugins/example-plugin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ function _M.access(conf, ctx)
return
end

function _M.header_filter(conf, ctx)
core.log.warn("plugin header_filter phase, conf: ", core.json.encode(conf))
end


function _M.body_filter(conf, ctx)
core.log.warn("plugin body_filter phase, eof: ", ngx.arg[2],
Expand All @@ -119,6 +123,10 @@ function _M.delayed_body_filter(conf, ctx)
", conf: ", core.json.encode(conf))
end

function _M.log(conf, ctx)
core.log.warn("plugin log phase, conf: ", core.json.encode(conf))
end


local function hello()
local args = ngx.req.get_uri_args()
Expand Down
11 changes: 9 additions & 2 deletions apisix/schema_def.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1032,8 +1032,15 @@ _M.plugin_injected_schema = {
description = "filter determines whether the plugin "..
"needs to be executed at runtime",
type = "array",
}
}
},
pre_function = {
description = "function to be executed in each phase " ..
"before execution of plugins. The pre_function will have access " ..
"to two arguments: `conf` and `ctx`.",
type = "string",
},
},
additionalProperties = false,
}
}

Expand Down
4 changes: 2 additions & 2 deletions t/admin/plugins.t
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ plugins:
}
}
--- response_body eval
qr/\{"metadata_schema":\{"properties":\{"ikey":\{"minimum":0,"type":"number"\},"skey":\{"type":"string"\}\},"required":\["ikey","skey"\],"type":"object"\},"priority":0,"schema":\{"\$comment":"this is a mark for our injected plugin schema","properties":\{"_meta":\{"properties":\{"disable":\{"type":"boolean"\},"error_response":\{"oneOf":\[\{"type":"string"\},\{"type":"object"\}\]\},"filter":\{"description":"filter determines whether the plugin needs to be executed at runtime","type":"array"\},"priority":\{"description":"priority of plugins by customized order","type":"integer"\}\},"type":"object"\},"i":\{"minimum":0,"type":"number"\},"ip":\{"type":"string"\},"port":\{"type":"integer"\},"s":\{"type":"string"\},"t":\{"minItems":1,"type":"array"\}\},"required":\["i"\],"type":"object"\},"version":0.1\}/
qr/\{"metadata_schema":\{"properties":\{"ikey":\{"minimum":0,"type":"number"\},"skey":\{"type":"string"\}\},"required":\["ikey","skey"\],"type":"object"\},"priority":0,"schema":\{"\$comment":"this is a mark for our injected plugin schema","properties":\{"_meta":\{"additionalProperties":false,"properties":\{"disable":\{"type":"boolean"\},"error_response":\{"oneOf":\[\{"type":"string"\},\{"type":"object"\}\]\},"filter":\{"description":"filter determines whether the plugin needs to be executed at runtime","type":"array"\},"pre_function":\{"description":"function to be executed in each phase before execution of plugins. The pre_function will have access to two arguments: `conf` and `ctx`.","type":"string"\},"priority":\{"description":"priority of plugins by customized order","type":"integer"\}\},"type":"object"\},"i":\{"minimum":0,"type":"number"\},"ip":\{"type":"string"\},"port":\{"type":"integer"\},"s":\{"type":"string"\},"t":\{"minItems":1,"type":"array"\}\},"required":\["i"\],"type":"object"\},"version":0.1\}/
Expand Down Expand Up @@ -382,7 +382,7 @@ qr/\{"encrypt_fields":\["password"\],"properties":\{"password":\{"type":"string"
}
}
--- response_body
{"priority":1003,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"_meta":{"properties":{"disable":{"type":"boolean"},"error_response":{"oneOf":[{"type":"string"},{"type":"object"}]},"filter":{"description":"filter determines whether the plugin needs to be executed at runtime","type":"array"},"priority":{"description":"priority of plugins by customized order","type":"integer"}},"type":"object"},"burst":{"minimum":0,"type":"integer"},"conn":{"exclusiveMinimum":0,"type":"integer"},"default_conn_delay":{"exclusiveMinimum":0,"type":"number"},"key":{"type":"string"},"key_type":{"default":"var","enum":["var","var_combination"],"type":"string"},"only_use_default_delay":{"default":false,"type":"boolean"}},"required":["conn","burst","default_conn_delay","key"],"type":"object"},"version":0.1}
{"priority":1003,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"_meta":{"additionalProperties":false,"properties":{"disable":{"type":"boolean"},"error_response":{"oneOf":[{"type":"string"},{"type":"object"}]},"filter":{"description":"filter determines whether the plugin needs to be executed at runtime","type":"array"},"pre_function":{"description":"function to be executed in each phase before execution of plugins. The pre_function will have access to two arguments: `conf` and `ctx`.","type":"string"},"priority":{"description":"priority of plugins by customized order","type":"integer"}},"type":"object"},"burst":{"minimum":0,"type":"integer"},"conn":{"exclusiveMinimum":0,"type":"integer"},"default_conn_delay":{"exclusiveMinimum":0,"type":"number"},"key":{"type":"string"},"key_type":{"default":"var","enum":["var","var_combination"],"type":"string"},"only_use_default_delay":{"default":false,"type":"boolean"}},"required":["conn","burst","default_conn_delay","key"],"type":"object"},"version":0.1}
Expand Down
Loading

0 comments on commit c2324a5

Please sign in to comment.