This is an automated email from the ASF dual-hosted git repository.
nic-6443 pushed a commit to branch fix/ai-proxy-client-disconnect
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/fix/ai-proxy-client-disconnect
by this push:
new 4de172aeb refactor: address review comments on lua_response_filter and
disconnect handler
4de172aeb is described below
commit 4de172aeb7b8a3a7980b989d8d41bfb2df5461a0
Author: Nic <[email protected]>
AuthorDate: Sat Apr 18 15:07:12 2026 +0800
refactor: address review comments on lua_response_filter and disconnect
handler
- update docstring to accurately reflect that lua_response_filter always
returns (ok, err) regardless of wait parameter
- avoid passing nil to ngx_flush: explicitly call ngx_flush(true) when
wait==true, ngx_flush() otherwise
- extract abort_on_disconnect local helper in parse_streaming_response
to deduplicate the log+close+mark-done pattern
Co-authored-by: Copilot <[email protected]>
---
apisix/plugin.lua | 19 ++++++++++++++-----
apisix/plugins/ai-providers/base.lua | 26 ++++++++++++--------------
2 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/apisix/plugin.lua b/apisix/plugin.lua
index 942efebe6..a09dc627a 100644
--- a/apisix/plugin.lua
+++ b/apisix/plugin.lua
@@ -1397,9 +1397,10 @@ function _M.run_global_rules(api_ctx, global_rules,
conf_version, phase_name)
end
end
--- @param wait boolean When true, use synchronous flush (ngx.flush(true)) and
return
--- (ok, err) so callers can detect client disconnection. Defaults to false
for
--- backward compatibility (async flush, no return value).
+-- @param wait boolean When true, use synchronous flush (ngx.flush(true)) so
callers
+-- can detect client disconnection. Defaults to false (async flush).
+-- @return boolean, string|nil Always returns (ok, err). On success returns
true.
+-- On flush failure or print failure returns false, err.
function _M.lua_response_filter(api_ctx, headers, body, wait)
local plugins = api_ctx.plugins
if not plugins or #plugins == 0 then
@@ -1408,7 +1409,11 @@ function _M.lua_response_filter(api_ctx, headers, body,
wait)
if not ok then
return false, err
end
- ok, err = ngx_flush(wait)
+ if wait then
+ ok, err = ngx_flush(true)
+ else
+ ok, err = ngx_flush()
+ end
if not ok then
return false, err
end
@@ -1443,7 +1448,11 @@ function _M.lua_response_filter(api_ctx, headers, body,
wait)
if not ok then
return false, err
end
- ok, err = ngx_flush(wait)
+ if wait then
+ ok, err = ngx_flush(true)
+ else
+ ok, err = ngx_flush()
+ end
if not ok then
return false, err
end
diff --git a/apisix/plugins/ai-providers/base.lua
b/apisix/plugins/ai-providers/base.lua
index 8227922d6..e8cfc77a3 100644
--- a/apisix/plugins/ai-providers/base.lua
+++ b/apisix/plugins/ai-providers/base.lua
@@ -272,6 +272,16 @@ function _M.parse_streaming_response(self, ctx, res,
target_proto, converter)
-- uncommitted and causing nginx to fall through to the balancer phase.
local output_sent = false
+ local function abort_on_disconnect(flush_err)
+ core.log.info("client disconnected during AI streaming, ",
+ "aborting upstream read: ", flush_err)
+ if res._httpc then
+ res._httpc:close()
+ res._httpc = nil
+ end
+ ctx.var.llm_request_done = true
+ end
+
while true do
local chunk, err = body_reader()
ctx.var.apisix_upstream_response_time = math.floor((ngx_now() -
@@ -359,13 +369,7 @@ function _M.parse_streaming_response(self, ctx, res,
target_proto, converter)
local ok, flush_err = plugin.lua_response_filter(ctx,
res.headers, c, true)
output_sent = true
if not ok then
- core.log.info("client disconnected during AI streaming, ",
- "aborting upstream read: ", flush_err)
- if res._httpc then
- res._httpc:close()
- res._httpc = nil
- end
- ctx.var.llm_request_done = true
+ abort_on_disconnect(flush_err)
return
end
end
@@ -373,13 +377,7 @@ function _M.parse_streaming_response(self, ctx, res,
target_proto, converter)
local ok, flush_err = plugin.lua_response_filter(ctx, res.headers,
chunk, true)
output_sent = true
if not ok then
- core.log.info("client disconnected during AI streaming, ",
- "aborting upstream read: ", flush_err)
- if res._httpc then
- res._httpc:close()
- res._httpc = nil
- end
- ctx.var.llm_request_done = true
+ abort_on_disconnect(flush_err)
return
end
end