Skip to content

fix(ai-aliyun-content-moderation): return nil instead of ngx.OK in lua_body_filter#13623

Merged
nic-6443 merged 2 commits into
apache:masterfrom
janiussyafiq:fix/13620-aliyun-final-packet-nonterminal
Jul 1, 2026
Merged

fix(ai-aliyun-content-moderation): return nil instead of ngx.OK in lua_body_filter#13623
nic-6443 merged 2 commits into
apache:masterfrom
janiussyafiq:fix/13620-aliyun-final-packet-nonterminal

Conversation

@janiussyafiq

@janiussyafiq janiussyafiq commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Description

ai-aliyun-content-moderation's lua_body_filter returned ngx.OK on the streaming final_packet path. In apisix/plugin.lua's lua_response_filter, returning a non-nil code prints the body and ngx.exits the whole response filter chain, so any lower-priority response body filter is skipped.

Because ai-aliyun-content-moderation (priority 1029) runs before ai-lakera-guard (priority 1028), a route chaining both terminated the chain before ai-lakera-guard's output scan ran — even though final_packet only annotates risk_level and never blocks. The result was a silent moderation gap: a streamed response that ai-lakera-guard would block could leak through unscanned.

This returns nil (transform-and-continue) instead of ngx.OK on the final_packet path, so the chain keeps running lower-priority response body filters. The paths that genuinely terminate the response (realtime block) still return a code and are unchanged.

A combined-plugin streaming test (t/plugin/ai-lakera-guard-chain.t) is added: it asserts ai-lakera-guard's output scan still runs and blocks a flagged stream when chained after ai-aliyun-content-moderation, and that a clean stream still passes through the chain.

Which issue(s) this PR fixes:

Fixes #13620
Fixes #13291

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. bug Something isn't working labels Jun 29, 2026
nic-6443
nic-6443 previously approved these changes Jun 29, 2026
membphis
membphis previously approved these changes Jun 29, 2026

@membphis membphis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review looks good to me. Please make sure CI is green before merging.

… chained

With lua_body_filter non-terminal, it re-runs on every streamed chunk once
llm_response_text is set. Moderate only once, and synthesize a [DONE]
terminator only when the stream is actually done, so chaining another
response-path plugin (e.g. ai-lakera-guard) after it can't double-moderate
or emit duplicate terminators.

Add a streaming chain test plus an X-AI-Fixture-Flush-Events fixture mode
that splits usage and done into separate chunks to exercise it.
@nic-6443
nic-6443 merged commit 4215731 into apache:master Jul 1, 2026
23 of 26 checks passed
@janiussyafiq
janiussyafiq deleted the fix/13620-aliyun-final-packet-nonterminal branch July 1, 2026 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

4 participants