diff --git a/apisix/patch.lua b/apisix/patch.lua index 31383b770128..4d6956720136 100644 --- a/apisix/patch.lua +++ b/apisix/patch.lua @@ -414,20 +414,22 @@ 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.* / + -- 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 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 a99311aa5499..672ec6c246f1 100644 --- a/t/core/request.t +++ b/t/core/request.t @@ -611,3 +611,58 @@ 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.* / 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 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") + + -- 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 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 +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 +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