diff --git a/apisix/core/table.lua b/apisix/core/table.lua index 60b0a6eba739..dd767859fd4c 100644 --- a/apisix/core/table.lua +++ b/apisix/core/table.lua @@ -31,6 +31,7 @@ local pairs = pairs local type = type local ngx_re = require("ngx.re") local isarray = require("table.isarray") +local str_has_prefix = require("apisix.core.string").has_prefix local _M = { @@ -130,7 +131,8 @@ do copied[orig] = copy for orig_key, orig_value in pairs(orig) do local path = parent .. "." .. tostring(orig_key) - if opts and array_find(opts.shallows, path) then + if opts and (array_find(opts.shallows, path) or + (opts.shallow_prefix and str_has_prefix(parent, opts.shallow_prefix))) then copy[orig_key] = orig_value else if type(orig_value) == "table" then diff --git a/apisix/plugin.lua b/apisix/plugin.lua index a2898bc0d404..afdf50f0bb2f 100644 --- a/apisix/plugin.lua +++ b/apisix/plugin.lua @@ -818,7 +818,10 @@ local function merge_consumer_route(route_conf, consumer_conf, consumer_group_co return route_conf end - local new_route_conf = core.table.deepcopy(route_conf) + -- the plugins subtree is fully overwritten below, so there is no need to + -- deep-copy it; shallow-copy that subtree to avoid the wasted work + local new_route_conf = core.table.deepcopy(route_conf, + { shallow_prefix = "self.value.plugins" }) if has_group_plugins then for name, conf in pairs(consumer_group_conf.value.plugins) do diff --git a/t/core/table.t b/t/core/table.t index 38616ae535bf..52e55162ee51 100644 --- a/t/core/table.t +++ b/t/core/table.t @@ -359,3 +359,37 @@ tab_copied.a.b.c == tab.a.b.c1: true tab_copied.a.b.c == t1: true tab_copied.x.y == tab.x.y: false tab_copied.x.y == t2: false + + + +=== TEST 13: shallow_prefix +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + local deepcopy = core.table.deepcopy + local plugin1 = {name = "plugin1"} + local plugin2 = {name = "plugin2"} + local tab = { + plugins = { + p1 = plugin1, + p2 = plugin2, + }, + } + + local tab_copied = deepcopy(tab, { shallow_prefix = "self.plugins" }) + + tab_copied.plugins.p1 = {name = "plugin1_new_modified"} + tab_copied.plugins.p2.name = "plugin2_modified" + + ngx.say("table copied: ", require("toolkit.json").encode(tab_copied)) + ngx.say("table original: ", require("toolkit.json").encode(tab)) + } + } +--- request +GET /t +--- response_body +table copied: {"plugins":{"p1":{"name":"plugin1_new_modified"},"p2":{"name":"plugin2_modified"}}} +table original: {"plugins":{"p1":{"name":"plugin1"},"p2":{"name":"plugin2_modified"}}} +--- no_error_log +[error]