You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2021/07/14 04:16:44 UTC

[apisix] branch master updated: feat: enable balancer phase for plugins (#4549)

This is an automated email from the ASF dual-hosted git repository.

spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 3509d1d  feat: enable balancer phase for plugins (#4549)
3509d1d is described below

commit 3509d1db9d42c6f2a81a74bb99fc379d339dc861
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Wed Jul 14 12:16:35 2021 +0800

    feat: enable balancer phase for plugins (#4549)
---
 apisix/balancer.lua   |  12 +++-
 apisix/init.lua       |   9 ++-
 apisix/plugin.lua     |   7 ++-
 t/debug/debug-mode.t  |   2 +-
 t/lib/server.lua      |  16 ++++++
 t/plugin/serverless.t | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 192 insertions(+), 10 deletions(-)

diff --git a/apisix/balancer.lua b/apisix/balancer.lua
index d5336b9..e6af3a3 100644
--- a/apisix/balancer.lua
+++ b/apisix/balancer.lua
@@ -286,8 +286,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
@@ -314,9 +315,16 @@ function _M.run(route, ctx)
             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 7c2f092..481b4c6 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -556,11 +556,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
 
 
@@ -711,7 +710,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
 
 
@@ -921,7 +920,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 c8824df..849b1e9 100644
--- a/apisix/plugin.lua
+++ b/apisix/plugin.lua
@@ -632,6 +632,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
@@ -649,6 +650,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
@@ -667,17 +669,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 08e776b..a3da953 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 0b6079f..006a4b4 100644
--- a/t/lib/server.lua
+++ b/t/lib/server.lua
@@ -397,6 +397,22 @@ 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
+
+
 function _M.v3_auth_authenticate()
     ngx.log(ngx.WARN, "etcd auth failed!")
 end
diff --git a/t/plugin/serverless.t b/t/plugin/serverless.t
index 2d78390..7a1b01b 100644
--- a/t/plugin/serverless.t
+++ b/t/plugin/serverless.t
@@ -679,3 +679,159 @@ 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
+--- skip_nginx: 4: < 1.19.3
+--- 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]
+
+
+
+=== 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