fix(stream/traffic-split): handle upstream_id set by plugin in stream context#13285
Conversation
… context
When the traffic-split plugin selects an upstream via upstream_id, it sets
api_ctx.upstream_id. In the HTTP path this is handled in handle_upstream()
which re-fetches the upstream and updates api_ctx.matched_upstream. The stream
path was missing this: it called set_by_route() which only checks
api_ctx.upstream_conf (for inline upstream objects), leaving api_ctx.matched_upstream
pointing to the route's original upstream.
Fix: after plugin.run_plugin("preread"), if api_ctx.upstream_id is set, fetch
that upstream and update api_ctx.matched_upstream before calling set_upstream.
There was a problem hiding this comment.
Pull request overview
Fixes stream (L4) routing so that when traffic-split (or another preread-phase plugin) selects an upstream via api_ctx.upstream_id, APISIX re-fetches that upstream and updates api_ctx.matched_upstream before calling upstream.set_by_route() / balancer selection—matching the HTTP-path behavior.
Changes:
- In
stream_preread_phase, afterplugin.run_plugin("preread"), resolveapi_ctx.upstream_idto an upstream object and updateapi_ctx.matched_upstream. - Add a stream test that configures
traffic-splitwithweighted_upstreams[].upstream_idand verifies the request is forwarded to the referenced upstream.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apisix/init.lua | Applies plugin-selected upstream_id to stream routing by refreshing matched_upstream after preread plugins run. |
| t/stream-plugin/traffic-split.t | Adds regression coverage for traffic-split selecting an upstream by upstream_id in stream context. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- get_by_id() already logs the error when upstream is not found, so the extra core.log.error call was redundant; remove it - delete earlier catch-all stream routes before upstream_id test to ensure route 3 is matched deterministically
|
Applied same fix as #13284 TEST 5: added |
|
Fixed the nginx.conf parse error. The issue was that TEST 5 had both |
When the traffic-split plugin selects an upstream via
upstream_id, it setsapi_ctx.upstream_id. In the HTTP path this is handled inhandle_upstream()which re-fetches the upstream and updatesapi_ctx.matched_upstream. The stream path was missing this handling.set_by_route()only checksapi_ctx.upstream_conf(set when using inline upstream objects), but doesn't handleapi_ctx.upstream_id. So even when the plugin selected a different upstream by ID, the route's original upstream was still used.The fix adds a check after
plugin.run_plugin("preread"): ifapi_ctx.upstream_idis set, fetch that upstream and updateapi_ctx.matched_upstreambefore callingset_upstream().Also adds a test case that configures a stream route with a traffic-split rule using
upstream_idand verifies traffic is correctly forwarded to the referenced upstream.