From f408d4a62eb18c934cb98147aad382a5006101aa Mon Sep 17 00:00:00 2001 From: bhuvan-somisetty Date: Thu, 15 Oct 2026 22:46:36 +0530 Subject: [PATCH 1/2] fix: invalidate req_post_args and post_arg.* cache on set_body_data In `apisix/patch.lua`, monkey-patched `ngx.req.set_body_data` only cleared `_request_body_table` and `_request_body_type`, leaving `api_ctx.req_post_args` with stale cached arguments from the pre-rewrite body. Additionally, clearing `post_arg.*` variables in `var._cache` was gated behind `api_ctx._request_body_table`, skipping variable invalidation if `_request_body_table` had not been populated or had already been cleared. This commit updates `ngx.req.set_body_data` to always invalidate `api_ctx.req_post_args` as well as any cached `post_arg.*` variables in `api_ctx.var._cache` regardless of `_request_body_table` status. Signed-off-by: bhuvan-somisetty --- apisix/patch.lua | 7 ++++--- t/core/request.t | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/apisix/patch.lua b/apisix/patch.lua index 31383b770128..26bc7e247c07 100644 --- a/apisix/patch.lua +++ b/apisix/patch.lua @@ -414,14 +414,15 @@ function _M.patch() end -- Patch ngx.req.set_body_data to invalidate the parsed request body cache - -- in api_ctx. This ensures that body lookups and post_arg.* variable - -- lookups after a body rewrite always reflect the new body content. + -- in api_ctx. This ensures that body lookups, get_post_args(), and post_arg.* + -- variable lookups after a body rewrite always reflect the new body content. local _orig_set_body_data = ngx.req.set_body_data ngx.req.set_body_data = function(data) local api_ctx = ngx.ctx.api_ctx - if api_ctx and api_ctx._request_body_table then + if api_ctx then api_ctx._request_body_table = nil api_ctx._request_body_type = nil + api_ctx.req_post_args = nil local var = api_ctx.var local cache = var and var._cache if cache then diff --git a/t/core/request.t b/t/core/request.t index a99311aa5499..c470edfe84c4 100644 --- a/t/core/request.t +++ b/t/core/request.t @@ -611,3 +611,53 @@ header: new body: nil err: request size 17 is greater than the maximum size 8 allowed kind: too_large + + + +=== TEST 20: set_body_data invalidates req_post_args and post_arg.* cache +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + core.ctx.set_vars_meta(api_ctx) + + -- 1. Read post args using core.request.get_post_args + local args1 = core.request.get_post_args(api_ctx) + ngx.say("args1 foo: ", args1["foo"]) + + -- 2. Read post_arg.foo variable via api_ctx.var (populates var._cache) + ngx.say("var post_arg.foo: ", api_ctx.var["post_arg.foo"]) + + -- 3. Rewrite body using ngx.req.set_body_data + ngx.req.set_body_data("foo=updated&bar=new") + + -- 4. Re-read post args: should reflect updated body + local args2 = core.request.get_post_args(api_ctx) + ngx.say("args2 foo: ", args2["foo"]) + ngx.say("args2 bar: ", args2["bar"]) + + -- 5. Re-read post_arg variable: should reflect updated body + ngx.say("updated var post_arg.foo: ", api_ctx.var["post_arg.foo"]) + ngx.say("updated var post_arg.bar: ", api_ctx.var["post_arg.bar"]) + } + } +--- request +POST /t +foo=initial&bar=original +--- more_headers +Content-Type: application/x-www-form-urlencoded +--- response_body +args1 foo: initial +var post_arg.foo: initial +args2 foo: updated +args2 bar: new +updated var post_arg.foo: updated +updated var post_arg.bar: new + From bc9ec16dca92ea1b3d6a61648d072b0b775af4d8 Mon Sep 17 00:00:00 2001 From: bhuvan-somisetty Date: Sun, 25 Oct 2026 23:37:34 +0530 Subject: [PATCH 2/2] fix: also invalidate post_arg_ variables on set_body_data Extend the var._cache invalidation loop in patched ngx.req.set_body_data to also match the legacy "post_arg_" prefix, preventing stale post_arg_foo variables after a request body rewrite. Also update TEST 20 in t/core/request.t to verify post_arg_ cache invalidation. Signed-off-by: bhuvan-somisetty --- apisix/patch.lua | 7 ++++--- t/core/request.t | 13 +++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apisix/patch.lua b/apisix/patch.lua index 26bc7e247c07..4d6956720136 100644 --- a/apisix/patch.lua +++ b/apisix/patch.lua @@ -414,8 +414,8 @@ function _M.patch() end -- Patch ngx.req.set_body_data to invalidate the parsed request body cache - -- in api_ctx. This ensures that body lookups, get_post_args(), and post_arg.* - -- variable lookups after a body rewrite always reflect the new body content. + -- in api_ctx. This ensures that body lookups, get_post_args(), and post_arg.* / + -- post_arg_* variable lookups after a body rewrite always reflect the new body content. local _orig_set_body_data = ngx.req.set_body_data ngx.req.set_body_data = function(data) local api_ctx = ngx.ctx.api_ctx @@ -428,7 +428,8 @@ function _M.patch() if cache then local keys_to_clear = {} for key in pairs(cache) do - if type(key) == "string" and key:sub(1, 9) == "post_arg." then + if type(key) == "string" and + (key:sub(1, 9) == "post_arg." or key:sub(1, 9) == "post_arg_") then keys_to_clear[#keys_to_clear + 1] = key end end diff --git a/t/core/request.t b/t/core/request.t index c470edfe84c4..672ec6c246f1 100644 --- a/t/core/request.t +++ b/t/core/request.t @@ -614,7 +614,7 @@ kind: too_large -=== TEST 20: set_body_data invalidates req_post_args and post_arg.* cache +=== TEST 20: set_body_data invalidates req_post_args and post_arg.* / post_arg_* cache --- config location /t { content_by_lua_block { @@ -632,8 +632,9 @@ kind: too_large local args1 = core.request.get_post_args(api_ctx) ngx.say("args1 foo: ", args1["foo"]) - -- 2. Read post_arg.foo variable via api_ctx.var (populates var._cache) + -- 2. Read post_arg.foo and post_arg_foo variables via api_ctx.var (populates var._cache) ngx.say("var post_arg.foo: ", api_ctx.var["post_arg.foo"]) + ngx.say("var post_arg_foo: ", api_ctx.var["post_arg_foo"]) -- 3. Rewrite body using ngx.req.set_body_data ngx.req.set_body_data("foo=updated&bar=new") @@ -643,9 +644,11 @@ kind: too_large ngx.say("args2 foo: ", args2["foo"]) ngx.say("args2 bar: ", args2["bar"]) - -- 5. Re-read post_arg variable: should reflect updated body + -- 5. Re-read post_arg variables: should reflect updated body ngx.say("updated var post_arg.foo: ", api_ctx.var["post_arg.foo"]) ngx.say("updated var post_arg.bar: ", api_ctx.var["post_arg.bar"]) + ngx.say("updated var post_arg_foo: ", api_ctx.var["post_arg_foo"]) + ngx.say("updated var post_arg_bar: ", api_ctx.var["post_arg_bar"]) } } --- request @@ -656,8 +659,10 @@ Content-Type: application/x-www-form-urlencoded --- response_body args1 foo: initial var post_arg.foo: initial +var post_arg_foo: initial args2 foo: updated args2 bar: new updated var post_arg.foo: updated updated var post_arg.bar: new - +updated var post_arg_foo: updated +updated var post_arg_bar: new