feat: add proxy-buffering plugin#13446
Open
AlinsRan wants to merge 22 commits into
Open
Conversation
The proxy-buffering plugin controls nginx proxy buffering behavior per route. When proxy buffering is disabled, nginx streams the response directly to the client without buffering, which is essential for Server-Sent Events (SSE), streaming APIs, and real-time data delivery. This commit also extends the APISIX HTTP pipeline with a dedicated nginx location (@disable_proxy_buffering) to handle routes where buffering should be disabled, similar to the existing @grpc_pass and @dubbo_pass locations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace AI-generated tests with tests based on actual streaming behavior: - Use hello_chunked upstream (chunked streaming) instead of /hello - Test baseline (without plugin) then with disable_proxy_buffering=true - Remove redundant schema validation and duplicate route tests - Update English doc: add canonical link, simplify description (remove internal priority detail), restructure to Examples format with named subsection - Update Chinese doc: add canonical link Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace AI-generated Test::Nginx integration tests with the enterprise edition test scripts. Keep only schema validation tests in .t file. - t/plugin/test_proxy_buffering.sh: shell script that tests SSE streaming via real HTTP requests against a running APISIX instance - t/test_sse.py: Python SSE server + client used by the shell script - t/certs/sse_server.crt, sse_server.key: TLS certs for SSL SSE test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The sse_server.key file contains base64 data with the string 'bRe' which codespell incorrectly flags as a misspelling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Re-add 'bre' to .ignore_words to fix codespell CI failure (the previous commit incorrectly removed it) - Add Apache license headers to t/test_sse.py and t/plugin/test_proxy_buffering.sh to fix check-license CI failure - Rename Response subclass to SseResponse to avoid shadowing aiohttp.web.Response import - Use headers.pop() instead of del to safely remove X-Accel-Buffering header even if absent - Add --fail-with-body to curl wrapper so Admin API errors fail the test - Add additionalProperties = false to plugin schema for stricter validation - Fix Required column value from 'False' to 'No' in docs attribute table Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The previous test_proxy_buffering.sh incorrectly tried to call the Admin API directly, which fails because CLI tests run without a live APISIX instance. Rewrite the test to follow the standard CLI test pattern (see test_dubbo.sh for reference): write conf/config.yaml, run 'make init', and verify the generated nginx.conf contains the expected directives. Also verify that the `@disable_proxy_buffering` location block is NOT generated when the plugin is not in the enabled plugins list. Remove t/cli/test_sse.py as it belongs to a live integration test context, not the CLI test framework.
Replace the live test_sse.py (which required a running APISIX instance) with a proper Test::Nginx .t test that: - Validates plugin schema (valid config, default values, invalid types) - Spins up an in-process SSE mock upstream using ngx.flush(true) to simulate real event-stream responses - Verifies SSE events are correctly proxied through when disable_proxy_buffering = true - Verifies responses are still delivered when disable_proxy_buffering = false
added 4 commits
May 28, 2026 09:47
…oid extra newline mismatch
- Restore test_sse.py with SseResponse class (avoids name collision with aiohttp's Response) and use .pop() instead of del for header removal - Rewrite test_proxy_buffering.sh to follow EE format: make run + Admin API route setup + real SSE streaming verification - Add Python dependencies (aiohttp, aiohttp-sse, sseclient) to CI runner - Remove mock .t test in favor of real SSE functional test
Without this, stale routes from this test would remain in etcd after make stop, causing subsequent tests (test_snippet.sh) to pick them up when they restart APISIX, leading to unexpected 502 responses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align with EE test coverage: - Add SSL test scenario: create SSL resource, route with HTTPS upstream, verify SSE streaming works end-to-end over TLS - Add t/certs/server.crt and t/certs/server.key (CN=localhost) for APISIX SSL termination in the SSL test - Add ssl argument support to test_sse.py: server starts with TLS using sse_server.crt/key, client connects to https://localhost:9443 with verify=False Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
proxy-bufferingplugin controls nginx proxy buffering behavior per route. When proxy buffering is disabled, nginx streams responses directly to clients without buffering, which is essential for Server-Sent Events (SSE), streaming APIs, and real-time data delivery.This plugin runs at a very high priority (21991) so it takes effect before authentication plugins, ensuring the streaming behavior is established early in the request lifecycle.
Changes
apisix/plugins/proxy-buffering.lua(priority: 21991)apisix/init.luawith adisable_proxy_buffering_access_phase()handler and routing checkapisix/cli/ngx_tpl.luawith a@disable_proxy_bufferingnginx location block (similar to@grpc_pass), wrapped in{% if enabled_plugins["proxy-buffering"] then %}make init+ nginx.conf verification patternExample
Requests to
/eventswill be proxied withproxy_buffering off, allowing SSE or chunked streaming responses to be delivered immediately to the client.