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 1a3467bdb fix: isolate logger response body buffers (#13450)
1a3467bdb is described below
commit 1a3467bdbac55c13870e876b116deb4a3151dbd1
Author: Nic <[email protected]>
AuthorDate: Mon Jun 1 16:11:17 2026 +0800
fix: isolate logger response body buffers (#13450)
---
apisix/core/response.lua | 28 ++++++++++++------
apisix/utils/log-util.lua | 5 +---
t/plugin/http-logger.t | 75 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 95 insertions(+), 13 deletions(-)
diff --git a/apisix/core/response.lua b/apisix/core/response.lua
index f1c22db8c..826e69b36 100644
--- a/apisix/core/response.lua
+++ b/apisix/core/response.lua
@@ -331,47 +331,57 @@ end
-- final_body = transform(final_body)
-- ngx.arg[1] = final_body
-- ...
-function _M.hold_body_chunk(ctx, hold_the_copy, max_resp_body_bytes)
+function _M.hold_body_chunk(ctx, hold_the_copy, max_resp_body_bytes,
body_buffer_key)
local body_buffer
local chunk, eof = arg[1], arg[2]
+ local buffer_key = body_buffer_key or ctx._plugin_name
if not ctx._body_buffer then
ctx._body_buffer = {}
end
if type(chunk) == "string" and chunk ~= "" then
- body_buffer = ctx._body_buffer[ctx._plugin_name]
+ body_buffer = ctx._body_buffer[buffer_key]
+ if body_buffer and body_buffer.done then
+ return nil
+ end
+
if not body_buffer then
body_buffer = {
chunk,
- n = 1
+ n = 1,
+ bytes = #chunk,
}
- ctx._body_buffer[ctx._plugin_name] = body_buffer
- ctx._resp_body_bytes = #chunk
+ ctx._body_buffer[buffer_key] = body_buffer
else
local n = body_buffer.n + 1
body_buffer.n = n
body_buffer[n] = chunk
- ctx._resp_body_bytes = ctx._resp_body_bytes + #chunk
+ body_buffer.bytes = body_buffer.bytes + #chunk
end
- if max_resp_body_bytes and ctx._resp_body_bytes >= max_resp_body_bytes
then
+
+ if max_resp_body_bytes and body_buffer.bytes >= max_resp_body_bytes
then
local body_data = concat_tab(body_buffer, "", 1, body_buffer.n)
body_data = str_sub(body_data, 1, max_resp_body_bytes)
+ body_buffer.done = true
return body_data
end
end
if eof then
- body_buffer = ctx._body_buffer[ctx._plugin_name]
+ body_buffer = ctx._body_buffer[buffer_key]
if not body_buffer then
if max_resp_body_bytes and #chunk >= max_resp_body_bytes then
chunk = str_sub(chunk, 1, max_resp_body_bytes)
end
return chunk
end
+ if body_buffer.done then
+ return nil
+ end
local body_data = concat_tab(body_buffer, "", 1, body_buffer.n)
- ctx._body_buffer[ctx._plugin_name] = nil
+ ctx._body_buffer[buffer_key] = nil
return body_data
end
diff --git a/apisix/utils/log-util.lua b/apisix/utils/log-util.lua
index 35a709814..4551b8c68 100644
--- a/apisix/utils/log-util.lua
+++ b/apisix/utils/log-util.lua
@@ -390,10 +390,7 @@ function _M.collect_body(conf, ctx)
if log_response_body then
local max_resp_body_bytes = conf.max_resp_body_bytes or
MAX_RESP_BODY
- if ctx._resp_body_bytes and ctx._resp_body_bytes >=
max_resp_body_bytes then
- return
- end
- local final_body = core.response.hold_body_chunk(ctx, true,
max_resp_body_bytes)
+ local final_body = core.response.hold_body_chunk(ctx, true,
max_resp_body_bytes, conf)
if not final_body then
return
end
diff --git a/t/plugin/http-logger.t b/t/plugin/http-logger.t
index e4eea99f3..e2693de62 100644
--- a/t/plugin/http-logger.t
+++ b/t/plugin/http-logger.t
@@ -821,3 +821,78 @@ hello world
--- error_log eval
qr/request log:(?!.*"body")/
--- wait: 1.5
+
+
+
+=== TEST 28: set global file logger and http logger with route file logger
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ t('/apisix/admin/global_rules/1', ngx.HTTP_DELETE)
+
+ local code, body = t('/apisix/admin/global_rules/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "http-logger": {
+ "uri": "http://127.0.0.1:1982/log",
+ "batch_max_size": 1,
+ "max_retry_count": 1,
+ "retry_delay": 2,
+ "buffer_duration": 2,
+ "inactive_timeout": 2,
+ "include_resp_body": true
+ },
+ "file-logger": {
+ "path": "global-file-with-resp-body.log",
+ "include_resp_body": true
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "file-logger": {
+ "path": "route-file-with-resp-body.log",
+ "include_resp_body": true
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1982": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 29: http logger keeps response body when file logger runs in global
rule and route
+--- request
+GET /hello
+--- response_body
+hello world
+--- error_log eval
+qr/request log:.*"response":\{"body":"hello world\\n"/
+--- wait: 1.5