From b3b6df7dac0a465b7c7c8410ed6f02bea924a27b Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Mon, 2 Feb 2026 16:57:42 +0100 Subject: [PATCH] No reply from proxy if interceptor releases request resources and returns a failed future (#142) See #141 This happens because ProxiedRequest#release is not protected from repeated invocations. Signed-off-by: Thomas Segismont --- .../vertx/httpproxy/impl/ProxiedRequest.java | 8 ++-- .../io/vertx/httpproxy/ProxyRequestTest.java | 41 ++++++++++++------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java b/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java index 47aafd1..414fe83 100644 --- a/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java +++ b/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java @@ -137,9 +137,11 @@ public HttpServerRequest proxiedRequest() { @Override public ProxyRequest release() { - body.stream().resume(); - headers.clear(); - body = null; + if (body != null) { + body.stream().resume(); + headers.clear(); + body = null; + } return this; } diff --git a/src/test/java/io/vertx/httpproxy/ProxyRequestTest.java b/src/test/java/io/vertx/httpproxy/ProxyRequestTest.java index 8269905..b8ca951 100644 --- a/src/test/java/io/vertx/httpproxy/ProxyRequestTest.java +++ b/src/test/java/io/vertx/httpproxy/ProxyRequestTest.java @@ -10,22 +10,9 @@ */ package io.vertx.httpproxy; -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.Promise; +import io.vertx.core.*; import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpClient; -import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.http.HttpClientRequest; -import io.vertx.core.http.HttpClientResponse; -import io.vertx.core.http.HttpHeaders; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.core.http.HttpVersion; -import io.vertx.core.http.RequestOptions; +import io.vertx.core.http.*; import io.vertx.core.net.NetClient; import io.vertx.core.net.NetSocket; import io.vertx.core.net.SocketAddress; @@ -579,6 +566,30 @@ public void testReleaseProxyRequest(TestContext ctx) { })); } + @Test + public void testReleaseProxyRequestAndFail(TestContext ctx) { + SocketAddress backend = startHttpBackend(ctx, 8081, req -> { + ctx.fail("Shouldn't be called"); + }); + HttpClient backendClient = vertx.createHttpClient(new HttpClientOptions(clientOptions)); + HttpProxy proxy = HttpProxy.reverseProxy(backendClient); + proxy.origin(backend); + proxy.addInterceptor(new ProxyInterceptor() { + @Override + public Future handleProxyRequest(ProxyContext context) { + context.request().release(); + return Future.failedFuture("boom"); + } + }); + startHttpServer(ctx, serverOptions, proxy); + HttpClient httpClient = vertx.createHttpClient(); + httpClient.request(HttpMethod.GET, 8080, "localhost", "/somepath").onComplete(ctx.asyncAssertSuccess(req -> { + req.send().onComplete(ctx.asyncAssertSuccess(resp -> { + ctx.assertEquals(502, resp.statusCode()); + })); + })); + } + @Test public void testSendDefaultProxyResponse(TestContext ctx) { startHttpServer(ctx, serverOptions, req -> {