From 16aece008a6a10dcf0662c57a21144b60b6e40e9 Mon Sep 17 00:00:00 2001 From: spacewander Date: Wed, 7 Jul 2021 10:01:27 +0800 Subject: [PATCH 1/3] feat: enable balancer phase for plugins Signed-off-by: spacewander --- apisix/balancer.lua | 14 +++++- apisix/init.lua | 9 ++-- apisix/plugin.lua | 7 ++- t/debug/debug-mode.t | 2 +- t/lib/server.lua | 16 +++++++ t/plugin/serverless.t | 103 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 141 insertions(+), 10 deletions(-) diff --git a/apisix/balancer.lua b/apisix/balancer.lua index 87042844b5f2..5de57233c844 100644 --- a/apisix/balancer.lua +++ b/apisix/balancer.lua @@ -282,8 +282,9 @@ do end -function _M.run(route, ctx) +function _M.run(route, ctx, plugin_funcs) local server, err + local header_changed if ctx.picked_server then -- use the server picked in the access phase @@ -300,15 +301,24 @@ function _M.run(route, ctx) return core.response.exit(502) end + plugin_funcs("balancer") + local pass_host = ctx.pass_host if pass_host == "node" and balancer.recreate_request then local host = server.domain or server.host if host ~= ctx.var.upstream_host then -- retried node has a different host ctx.var.upstream_host = host - balancer.recreate_request() + header_changed = true end end + + end + + local _, run = plugin_funcs("balancer") + -- always recreate request as the request may be changed by plugins + if (run or header_changed) and balancer.recreate_request then + balancer.recreate_request() end core.log.info("proxy request to ", server.host, ":", server.port) diff --git a/apisix/init.lua b/apisix/init.lua index 3fc3ac4cbe87..521bc651ba72 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -551,11 +551,10 @@ local function common_phase(phase_name) if api_ctx.script_obj then script.run(phase_name, api_ctx) - else - plugin.run_plugin(phase_name, nil, api_ctx) + return api_ctx, true end - return api_ctx + return plugin.run_plugin(phase_name, nil, api_ctx) end @@ -706,7 +705,7 @@ function _M.http_balancer_phase() return core.response.exit(500) end - load_balancer.run(api_ctx.matched_route, api_ctx) + load_balancer.run(api_ctx.matched_route, api_ctx, common_phase) end @@ -916,7 +915,7 @@ function _M.stream_balancer_phase() return ngx_exit(1) end - load_balancer.run(api_ctx.matched_route, api_ctx) + load_balancer.run(api_ctx.matched_route, api_ctx, common_phase) end diff --git a/apisix/plugin.lua b/apisix/plugin.lua index 7dead03cccb2..8c15d8817258 100644 --- a/apisix/plugin.lua +++ b/apisix/plugin.lua @@ -622,6 +622,7 @@ end function _M.run_plugin(phase, plugins, api_ctx) + local plugin_run = false api_ctx = api_ctx or ngx.ctx.api_ctx if not api_ctx then return @@ -639,6 +640,7 @@ function _M.run_plugin(phase, plugins, api_ctx) for i = 1, #plugins, 2 do local phase_func = plugins[i][phase] if phase_func then + plugin_run = true local code, body = phase_func(plugins[i + 1], api_ctx) if code or body then if is_http then @@ -657,17 +659,18 @@ function _M.run_plugin(phase, plugins, api_ctx) end end end - return api_ctx + return api_ctx, plugin_run end for i = 1, #plugins, 2 do local phase_func = plugins[i][phase] if phase_func then + plugin_run = true phase_func(plugins[i + 1], api_ctx) end end - return api_ctx + return api_ctx, plugin_run end diff --git a/t/debug/debug-mode.t b/t/debug/debug-mode.t index 08e776b7a53c..a3da9534c87e 100644 --- a/t/debug/debug-mode.t +++ b/t/debug/debug-mode.t @@ -236,7 +236,7 @@ passed GET /hello --- yaml_config eval: $::yaml_config --- response_headers -Apisix-Plugins: response-rewrite, limit-conn, limit-count, response-rewrite +Apisix-Plugins: response-rewrite, limit-conn, limit-count, response-rewrite, response-rewrite --- response_body yes --- error_log diff --git a/t/lib/server.lua b/t/lib/server.lua index e7621044489d..1066afb4a07b 100644 --- a/t/lib/server.lua +++ b/t/lib/server.lua @@ -418,4 +418,20 @@ function _M.server_error() end +function _M.log_request() + ngx.log(ngx.WARN, "uri: ", ngx.var.uri) + local headers = ngx.req.get_headers() + + local keys = {} + for k in pairs(headers) do + table.insert(keys, k) + end + table.sort(keys) + + for _, key in ipairs(keys) do + ngx.log(ngx.WARN, key, ": ", headers[key]) + end +end + + return _M diff --git a/t/plugin/serverless.t b/t/plugin/serverless.t index 2d78390e7340..a1e634fdfd73 100644 --- a/t/plugin/serverless.t +++ b/t/plugin/serverless.t @@ -679,3 +679,106 @@ GET /hello --- error_log default phase: access match uri /hello + + + +=== TEST 23: run in the balancer phase +--- 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": { + "serverless-pre-function": { + "phase": "balancer", + "functions" : ["return function(conf, ctx) ngx.req.set_header('X-SERVERLESS', ctx.balancer_ip) end"] + } + }, + "upstream": { + "nodes": { + "127.0.0.2:1979": 100000, + "127.0.0.1:1980": 1 + }, + "type": "chash", + "key": "remote_addr" + }, + "uri": "/log_request" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 24: check plugin +--- request +GET /log_request +--- grep_error_log eval +qr/(proxy request to \S+|x-serverless: [\d.]+)/ +--- grep_error_log_out +proxy request to 127.0.0.2:1979 +proxy request to 127.0.0.1:1980 +x-serverless: 127.0.0.1 + + + +=== TEST 25: exit in the balancer phase +--- 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": { + "serverless-pre-function": { + "phase": "balancer", + "functions" : ["return function(conf, ctx) ngx.exit(403) end"] + } + }, + "upstream": { + "nodes": { + "127.0.0.2:1979": 100000, + "127.0.0.1:1980": 1 + }, + "type": "chash", + "key": "remote_addr" + }, + "uri": "/log_request" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 26: check plugin +--- request +GET /log_request +--- error_code: 403 +--- no_error_log +[error] From 5ccd8c50ff65abe7d63566a19310fcba140aa94d Mon Sep 17 00:00:00 2001 From: spacewander Date: Wed, 7 Jul 2021 11:31:08 +0800 Subject: [PATCH 2/3] skip for low version openresty Signed-off-by: spacewander --- t/plugin/serverless.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/plugin/serverless.t b/t/plugin/serverless.t index a1e634fdfd73..9b4789b35ca6 100644 --- a/t/plugin/serverless.t +++ b/t/plugin/serverless.t @@ -726,6 +726,7 @@ passed === TEST 24: check plugin --- request GET /log_request +--- skip_nginx: 4: < 1.19.3 --- grep_error_log eval qr/(proxy request to \S+|x-serverless: [\d.]+)/ --- grep_error_log_out From 9e1ff5ad70ab7a19e62bf0075f45b4b67944d860 Mon Sep 17 00:00:00 2001 From: spacewander Date: Wed, 14 Jul 2021 10:51:49 +0800 Subject: [PATCH 3/3] ensure balancer phase run correct time Signed-off-by: spacewander --- apisix/balancer.lua | 2 -- t/plugin/serverless.t | 52 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/apisix/balancer.lua b/apisix/balancer.lua index 1965d0490d85..e6af3a3f6eb3 100644 --- a/apisix/balancer.lua +++ b/apisix/balancer.lua @@ -309,8 +309,6 @@ function _M.run(route, ctx, plugin_funcs) return core.response.exit(502) end - plugin_funcs("balancer") - local pass_host = ctx.pass_host if pass_host == "node" and balancer.recreate_request then local host = server.domain or server.host diff --git a/t/plugin/serverless.t b/t/plugin/serverless.t index 9b4789b35ca6..7a1b01befef4 100644 --- a/t/plugin/serverless.t +++ b/t/plugin/serverless.t @@ -783,3 +783,55 @@ GET /log_request --- error_code: 403 --- no_error_log [error] + + + +=== TEST 27: ensure balancer phase run correct time +--- 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": { + "serverless-pre-function": { + "phase": "balancer", + "functions" : ["return function(conf, ctx) ngx.log(ngx.WARN, 'run balancer phase with ', ctx.balancer_ip) end"] + } + }, + "upstream": { + "nodes": { + "127.0.0.2:1979": 100000, + "127.0.0.1:1980": 1 + }, + "type": "chash", + "key": "remote_addr" + }, + "uri": "/log_request" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 28: check plugin +--- request +GET /log_request +--- grep_error_log eval +qr/(run balancer phase with [\d.]+)/ +--- grep_error_log_out +run balancer phase with 127.0.0.2 +run balancer phase with 127.0.0.1