diff --git a/apisix/plugin.lua b/apisix/plugin.lua index e0f2dbdc014b..090be6629c94 100644 --- a/apisix/plugin.lua +++ b/apisix/plugin.lua @@ -415,6 +415,13 @@ local function meta_filter(ctx, plugin_name, plugin_conf) return true end + local match_cache_key = + ctx.conf_type .. "#" .. ctx.conf_id .. "#" + .. ctx.conf_version .. "#" .. plugin_name .. "#meta_filter_matched" + if ctx[match_cache_key] ~= nil then + return ctx[match_cache_key] + end + local ex, ok, err if ctx then ex, err = expr_lrucache(plugin_name .. ctx.conf_type .. ctx.conf_id, @@ -433,6 +440,8 @@ local function meta_filter(ctx, plugin_name, plugin_conf) " plugin_name: ", plugin_name) return true end + + ctx[match_cache_key] = ok return ok end @@ -457,9 +466,7 @@ function _M.filter(ctx, conf, plugins, route_conf, phase) goto continue end - local matched = meta_filter(ctx, name, plugin_conf) - local disable = check_disable(plugin_conf) - if not disable and matched then + if not check_disable(plugin_conf) then if plugin_obj.run_policy == "prefer_route" and route_plugin_conf ~= nil then local plugin_conf_in_route = route_plugin_conf[name] local disable_in_route = check_disable(plugin_conf_in_route) @@ -941,8 +948,12 @@ function _M.run_plugin(phase, plugins, api_ctx) end if phase_func then - plugin_run = true local conf = plugins[i + 1] + if not meta_filter(api_ctx, plugins[i]["name"], conf)then + goto CONTINUE + end + + plugin_run = true local code, body = phase_func(conf, api_ctx) if code or body then if is_http then @@ -975,9 +986,10 @@ function _M.run_plugin(phase, plugins, api_ctx) for i = 1, #plugins, 2 do local phase_func = plugins[i][phase] - if phase_func then + local conf = plugins[i + 1] + if phase_func and meta_filter(api_ctx, plugins[i]["name"], conf) then plugin_run = true - phase_func(plugins[i + 1], api_ctx) + phase_func(conf, api_ctx) end end diff --git a/t/plugin/plugin.t b/t/plugin/plugin.t index 5baaed8011a6..42563e89f4dc 100644 --- a/t/plugin/plugin.t +++ b/t/plugin/plugin.t @@ -520,8 +520,220 @@ passed -=== TEST 18: hit route: run proxy-rewrite plugin +=== TEST 18: hit route: run global proxy-rewrite plugin --- request GET /hello1?version=v4 --- response_headers x-api-version: v4 + + + +=== TEST 19: different global_rules with the same plugin will not use the same meta.filter cache +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/global_rules/3', + ngx.HTTP_PUT, + { + plugins = { + ["proxy-rewrite"] = { + _meta = { + filter = { + {"arg_version", "==", "v5"} + } + }, + uri = "/echo", + headers = { + ["X-Api-Version"] = "v5" + } + } + } + } + ) + if code >= 300 then + ngx.print(body) + else + ngx.say(body) + end + } + } +--- response_body +passed + + + +=== TEST 20: hit global_rules which has the same plugin with different meta.filter +--- pipelined_requests eval +["GET /hello1?version=v4", "GET /hello1?version=v5"] +--- response_headers eval +["x-api-version: v4", "x-api-version: v5"] + + + +=== TEST 21: use _meta.filter in response-rewrite plugin +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "response-rewrite": { + "_meta": { + "filter": [ + ["upstream_status", "~=", 200] + ] + }, + "headers": { + "set": { + "test-header": "error" + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 22: upstream_status = 502, enable response-rewrite plugin +--- request +GET /specific_status +--- more_headers +x-test-upstream-status: 502 +--- response_headers +test-header: error +--- error_code: 502 + + + +=== TEST 23: upstream_status = 200, disable response-rewrite plugin +--- request +GET /hello +--- response_headers +!test-header + + + +=== TEST 24: use _meta.filter in response-rewrite plugin +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "headers": { + "foo-age": "$arg_age" + } + }, + "response-rewrite": { + "_meta": { + "filter": [ + ["http_foo_age", "==", "18"] + ] + }, + "status_code": 403 + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 25: proxy-rewrite plugin will set $http_foo_age, response-rewrite plugin return 403 +--- request +GET /hello?age=18 +--- error_code: 403 + + + +=== TEST 26: response-rewrite plugin disable, return 200 +--- request +GET /hello + + + +=== TEST 27: use response var in meta.filter +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "_meta": { + "filter": [ + ["upstream_status", "==", "200"] + ] + }, + "uri": "/echo", + "headers": { + "x-version": "v1" + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 28: hit route: disable proxy-rewrite plugin +--- request +GET /hello +--- response_headers +!x-version