From 065affe32519b5d7d0ad0200176cffe701b6e0b9 Mon Sep 17 00:00:00 2001 From: Alexey Nesterov Date: Thu, 14 Nov 2019 16:24:46 +0000 Subject: [PATCH] Keep Host header in the outbound request (#1412) Commit 0d2b87a changed how outbound request headers are updated, instead of using HttpClientOperations.headers() method to merged headers, HttpHeaders.add() is now used. However HttpClientOperations.headers() method treats Host header specially and do not override it from the provided headers collection. This fix just copies the same logic within NettyRoutingFilter for backward compatibility. There is one issue with this approach, if Host header is set by a filter it will be ignored. However this is how it worked before, with HttpClientOperations.headers() method in place. gh-1345 --- .../cloud/gateway/filter/NettyRoutingFilter.java | 4 ++++ .../filter/NettyRoutingFilterIntegrationTests.java | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java index baf274f0..72c885d4 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java @@ -122,6 +122,10 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered { String host = request.getHeaders().getFirst(HttpHeaders.HOST); headers.add(HttpHeaders.HOST, host); } + else { + // let Netty set it based on hostname + headers.remove(HttpHeaders.HOST); + } }).request(method).uri(url).send((req, nettyOutbound) -> { if (log.isTraceEnabled()) { nettyOutbound.withConnection(connection -> log.trace( diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java index 08d7a997..16845423 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java @@ -27,6 +27,7 @@ import org.springframework.context.annotation.Import; import org.springframework.http.HttpStatus; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @@ -46,6 +47,18 @@ public class NettyRoutingFilterIntegrationTests extends BaseWebClientTests { .isEqualTo("Response took longer than timeout: PT3S"); } + @Test + public void outboundHostHeaderNotOverwrittenByInbound() { + // different base url to have different host header in inbound / outbound requests + // Host: 127.0.0.1 -> request to Gateway, Host: localhost -> request from Gateway, + // resolved from lb://testservice + WebTestClient client = testClient.mutate().baseUrl("http://127.0.0.1:" + port) + .build(); + + client.get().uri("/headers").exchange().expectBody().jsonPath("$.headers.host") + .isEqualTo("localhost:" + port); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class)