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

nic-6443 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 51fad8a89 fix(traffic-label): cache the compiled match expressions 
outside the plugin config (#13901)
51fad8a89 is described below

commit 51fad8a897d538a68b8283d1e9a428363889df0a
Author: Nic <[email protected]>
AuthorDate: Tue Sep 1 14:31:01 2026 +0800

    fix(traffic-label): cache the compiled match expressions outside the plugin 
config (#13901)
---
 apisix/plugins/traffic-label.lua | 25 +++++++++-------
 t/plugin/traffic-label2.t        | 63 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/apisix/plugins/traffic-label.lua b/apisix/plugins/traffic-label.lua
index 65eb71e53..e57169b38 100644
--- a/apisix/plugins/traffic-label.lua
+++ b/apisix/plugins/traffic-label.lua
@@ -21,6 +21,7 @@ local expr          = require("resty.expr.v1")
 local roundrobin    = require("resty.roundrobin")
 local ipairs        = ipairs
 local pairs         = pairs
+local setmetatable  = setmetatable
 
 local lrucache = core.lrucache.new({
     ttl = 0, count = 512
@@ -192,19 +193,23 @@ end
 function _M.access(conf, ctx)
     local match_result
 
-    if not conf.rules_arr then
-        conf.rules_arr = {}
-
-        for _, rule in ipairs(conf.rules) do
+    for _, rule in ipairs(conf.rules) do
+        if not rule._expr then
             -- if no rule.match, use {} to match all request
-            local expr, _ = expr.new(rule.match or {})
-            core.table.insert_tail(conf.rules_arr, expr)
+            local rule_expr, err = expr.new(rule.match or {})
+            if not rule_expr then
+                core.log.error("failed to create the 'match' expression: ", 
err)
+                return
+            end
+
+            -- Hide the compiled expression in a metatable so that it stays 
out of
+            -- the configuration: the "ipmatch" operator compiles into an 
ipmatcher,
+            -- whose lookup tables are keyed by integers, and a configuration 
holding
+            -- one can no longer be JSON encoded.
+            setmetatable(rule, {__index = {_expr = rule_expr}})
         end
-    end
 
-    for i, rule in ipairs(conf.rules) do
-        local expr = conf.rules_arr[i]
-        match_result = expr:eval(ctx.var)
+        match_result = rule._expr:eval(ctx.var)
 
         if match_result then
             local action = next_action(rule.actions)
diff --git a/t/plugin/traffic-label2.t b/t/plugin/traffic-label2.t
index 70271f20d..422af3b57 100644
--- a/t/plugin/traffic-label2.t
+++ b/t/plugin/traffic-label2.t
@@ -551,3 +551,66 @@ qr/property \\"rules\\" is required/
 --- error_code: 400
 --- response_body eval
 qr/expect array to have at least 1 items/
+
+
+
+=== TEST 19: set route with an ipmatch match expression
+--- 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": {
+                            "traffic-label": {
+                                "rules": [
+                                    {
+                                        "match": [
+                                            [
+                                                "http_x_forwarded_for",
+                                                "ipmatch",
+                                                ["10.7.22.0/24"]
+                                            ]
+                                        ],
+                                        "actions": [
+                                            {
+                                                "set_headers": {
+                                                    "X-server-id": 100
+                                                }
+                                            }
+                                        ]
+                                    }
+                                ]
+                            }
+                        },
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/echo"
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 20: the route config stays serialisable once the expression is 
compiled
+--- pipelined_requests eval
+["GET /echo", "GET /echo"]
+--- more_headers
+X-Forwarded-For: 10.7.22.1
+--- error_code eval
+[200, 200]
+--- no_error_log
+[error]
+excessively sparse array

Reply via email to