diff --git a/src/main/java/io/vertx/httpproxy/impl/HttpUtils.java b/src/main/java/io/vertx/httpproxy/impl/HttpUtils.java index 707c5b7..161271f 100644 --- a/src/main/java/io/vertx/httpproxy/impl/HttpUtils.java +++ b/src/main/java/io/vertx/httpproxy/impl/HttpUtils.java @@ -18,8 +18,25 @@ import java.time.Instant; import java.util.List; +import static io.vertx.core.http.HttpHeaders.*; + class HttpUtils { + // https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1 + private static final MultiMap HOP_BY_HOP_HEADERS = MultiMap.caseInsensitiveMultiMap() + .add(CONNECTION, "whatever") + .add(KEEP_ALIVE, "whatever") + .add(PROXY_AUTHENTICATE, "whatever") + .add(PROXY_AUTHORIZATION, "whatever") + .add("te", "whatever") + .add("trailer", "whatever") + .add(TRANSFER_ENCODING, "whatever") + .add(UPGRADE, "whatever"); + + static boolean isHopByHopHeader(String name) { + return HOP_BY_HOP_HEADERS.contains(name); + } + static Boolean isChunked(MultiMap headers) { List te = headers.getAll("transfer-encoding"); if (te != null) { diff --git a/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java b/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java index 751f8b3..787f1ce 100644 --- a/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java +++ b/src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java @@ -44,16 +44,6 @@ public class ProxiedRequest implements ProxyRequest { private static final int FLAG_FORWARD_PORT = 8; // bit 3 private static final int FLAG_USE_RFC7239 = 16; // bit 4 - private static final MultiMap HOP_BY_HOP_HEADERS = MultiMap.caseInsensitiveMultiMap() - .add(CONNECTION, "whatever") - .add(KEEP_ALIVE, "whatever") - .add(PROXY_AUTHENTICATE, "whatever") - .add(PROXY_AUTHORIZATION, "whatever") - .add("te", "whatever") - .add("trailer", "whatever") - .add(TRANSFER_ENCODING, "whatever") - .add(UPGRADE, "whatever"); - final ContextInternal context; private HttpMethod method; private final HttpVersion version; @@ -203,7 +193,7 @@ Future sendRequest() { for (Map.Entry header : headers) { String name = header.getKey(); String value = header.getValue(); - if (!HOP_BY_HOP_HEADERS.contains(name) && !name.equalsIgnoreCase(HttpHeaders.HOST.toString())) { + if (!HttpUtils.isHopByHopHeader(name) && !name.equalsIgnoreCase(HttpHeaders.HOST.toString())) { request.headers().add(name, value); } } diff --git a/src/main/java/io/vertx/httpproxy/impl/ProxiedResponse.java b/src/main/java/io/vertx/httpproxy/impl/ProxiedResponse.java index 3431722..190b281 100644 --- a/src/main/java/io/vertx/httpproxy/impl/ProxiedResponse.java +++ b/src/main/java/io/vertx/httpproxy/impl/ProxiedResponse.java @@ -212,7 +212,9 @@ public Future send() { String value = header.getValue(); if (name.equals("content-type") && body != null) { // Skip - } else if (name.equalsIgnoreCase("date") || name.equalsIgnoreCase("warning") || name.equalsIgnoreCase("transfer-encoding")) { + } else if (name.equalsIgnoreCase("date") + || name.equalsIgnoreCase("warning") + || HttpUtils.isHopByHopHeader(name)) { // Skip } else { proxiedResponse.headers().add(name, value); diff --git a/src/test/java/io/vertx/tests/ProxyClientKeepAliveTest.java b/src/test/java/io/vertx/tests/ProxyClientKeepAliveTest.java index 4253878..c6919ff 100644 --- a/src/test/java/io/vertx/tests/ProxyClientKeepAliveTest.java +++ b/src/test/java/io/vertx/tests/ProxyClientKeepAliveTest.java @@ -736,6 +736,34 @@ public void testPropagateHeaders(TestContext ctx) { })); } + @Test + public void testIgnoreHopByHopResponseHeaders(TestContext ctx) { + SocketAddress backend = startHttpBackend(ctx, 8081, req -> { + req.response() + .putHeader("Connection", "keep-alive") + .putHeader("Keep-Alive", "timeout=5") + .putHeader("X-End-To-End", "should-forward") + .end("ok"); + }); + startProxy(backend); + client = vertx.createHttpClient(); + Async latch = ctx.async(); + client.request(GET, 8080, "localhost", "/").onComplete(ctx.asyncAssertSuccess(req -> { + req.send() + .compose(resp -> { + ctx.assertEquals(200, resp.statusCode()); + ctx.assertEquals("should-forward", resp.getHeader("x-end-to-end")); + ctx.assertNull(resp.getHeader("connection")); + ctx.assertNull(resp.getHeader("keep-alive")); + return resp.body(); + }) + .onComplete(ctx.asyncAssertSuccess(body -> { + ctx.assertEquals("ok", body.toString()); + latch.complete(); + })); + })); + } + @Test public void testIPV6Authority(TestContext ctx) { testAuthority(ctx, HostAndPort.authority("[7a03:908:671:b520:ba27:bbff:ffff:fed2]", 1234));