- severity: Medium-High
- files:
shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/WebClientMessageWriter.java:70
- description: The
ResponseEntity<Flux<DataBuffer>> set into CLIENT_RESPONSE_ATTR by WebClientPlugin holds a lazy body Flux; the reactor-netty connection is not returned to the pool until that Flux is subscribed and drained/cancelled. onErrorResume/doOnCancel here only cover errors during exchange.getResponse().writeWith(body) (inside the defer); there is no guard on chain.execute(exchange) itself. If any plugin running after the WebClient call throws or the chain is cancelled, the defer is never reached, the body Flux is never subscribed, and the connection is held until the client idle/recv timeout. Sibling NettyClientMessageWriter.java:59,82 correctly guards the same path with doOnError/doOnCancel → cleanup(exchange).
- impact: Leaked upstream connections (not returned to the WebClient/reactor-netty pool) on any mid-chain failure; pool starvation under sustained mid-chain failures.
- suggested_fix: Add
.doOnError(e -> clean(exchange)).doOnCancel(() -> clean(exchange)) to chain.execute(exchange) at line 70, mirroring NettyClientMessageWriter (clean already drains/releases the body at line 128).
- confidence: Medium-High
Identified during the 2026-08-02 deep re-scan; full list in docs/scan2-2026-08-02/06-medium-tiers.md.
shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/WebClientMessageWriter.java:70ResponseEntity<Flux<DataBuffer>>set intoCLIENT_RESPONSE_ATTRbyWebClientPluginholds a lazy body Flux; the reactor-netty connection is not returned to the pool until that Flux is subscribed and drained/cancelled.onErrorResume/doOnCancelhere only cover errors duringexchange.getResponse().writeWith(body)(inside thedefer); there is no guard onchain.execute(exchange)itself. If any plugin running after the WebClient call throws or the chain is cancelled, thedeferis never reached, the body Flux is never subscribed, and the connection is held until the client idle/recv timeout. SiblingNettyClientMessageWriter.java:59,82correctly guards the same path withdoOnError/doOnCancel→cleanup(exchange)..doOnError(e -> clean(exchange)).doOnCancel(() -> clean(exchange))tochain.execute(exchange)at line 70, mirroringNettyClientMessageWriter(cleanalready drains/releases the body at line 128).Identified during the 2026-08-02 deep re-scan; full list in
docs/scan2-2026-08-02/06-medium-tiers.md.