diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index 2da24fe6b0..abcc7d1f0f 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -442,8 +442,9 @@ public HeaderRoutePredicateFactory headerRoutePredicateFactory() { @Bean @ConditionalOnEnabledPredicate - public HostRoutePredicateFactory hostRoutePredicateFactory() { - return new HostRoutePredicateFactory(); + public HostRoutePredicateFactory hostRoutePredicateFactory(Environment env) { + boolean includePort = env.getProperty("spring.cloud.gateway.predicate.host.include-port", Boolean.class, true); + return new HostRoutePredicateFactory(includePort); } @Bean diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactory.java index 9cf82025f8..a2a07a99a7 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactory.java @@ -35,16 +35,27 @@ */ public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory { + private boolean includePort = true; + private PathMatcher pathMatcher = new AntPathMatcher("."); public HostRoutePredicateFactory() { + this(true); + } + + public HostRoutePredicateFactory(boolean includePort) { super(Config.class); + this.includePort = includePort; } public void setPathMatcher(PathMatcher pathMatcher) { this.pathMatcher = pathMatcher; } + /* for testing */ void setIncludePort(boolean includePort) { + this.includePort = includePort; + } + @Override public List shortcutFieldOrder() { return Collections.singletonList("patterns"); @@ -60,25 +71,35 @@ public Predicate apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange exchange) { - InetSocketAddress address = exchange.getRequest().getHeaders().getHost(); - if (address != null) { - String match = null; - String host = address.getHostName(); - for (int i = 0; i < config.getPatterns().size(); i++) { - String pattern = config.getPatterns().get(i); - if (pathMatcher.match(pattern, host)) { - match = pattern; - break; - } + String host; + if (includePort) { + host = exchange.getRequest().getHeaders().getFirst("Host"); + } + else { + InetSocketAddress address = exchange.getRequest().getHeaders().getHost(); + if (address != null) { + host = address.getHostString(); + } + else { + return false; } + } - if (match != null) { - Map variables = pathMatcher.extractUriTemplateVariables(match, host); - ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables); - return true; + String match = null; + for (int i = 0; i < config.getPatterns().size(); i++) { + String pattern = config.getPatterns().get(i); + if (pathMatcher.match(pattern, host)) { + match = pattern; + break; } + } + if (match != null) { + Map variables = pathMatcher.extractUriTemplateVariables(match, host); + ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables); + return true; } + return false; } diff --git a/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 79d80429be..d4fc0a5430 100644 --- a/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -418,6 +418,12 @@ "type": "java.lang.Boolean", "description": "If Micrometer Observability support should be turned on.", "defaultValue": "true" + }, + { + "name": "spring.cloud.gateway.predicate.host.include-port", + "type": "java.lang.Boolean", + "description": "Include the port in matching the host name.", + "defaultValue": "true" } ] } diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java index b6a528d190..e70b34dd42 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java @@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -41,6 +42,9 @@ @DirtiesContext public class HostRoutePredicateFactoryTests extends BaseWebClientTests { + @Autowired + private HostRoutePredicateFactory hostPredicate; + @Test public void hostRouteWorks() { expectHostRoute("www.example.org", "host_example_to_httpbin"); @@ -76,7 +80,11 @@ public void mulitHostRouteDslWorks() { @Test public void sameHostWithPort() { - expectHostRoute("hostpatternarg.org:8080", "without_pattern"); + expectHostRoute("hostpatternarg.org:8080", "host_with_port_pattern"); + + hostPredicate.setIncludePort(false); + expectHostRoute("hostpatternarg.org:8080", "host_without_port_pattern"); + hostPredicate.setIncludePort(true); } @Test diff --git a/spring-cloud-gateway-server/src/test/resources/application.yml b/spring-cloud-gateway-server/src/test/resources/application.yml index 5e62bd4b28..2b1fde1351 100644 --- a/spring-cloud-gateway-server/src/test/resources/application.yml +++ b/spring-cloud-gateway-server/src/test/resources/application.yml @@ -216,7 +216,15 @@ spring: # ===================================== - - id: without_pattern + - id: host_with_port_pattern + uri: ${test.uri} + predicates: + - name: Host + args: + pattern: 'hostpatternarg.org:8080' + + # ===================================== + - id: host_without_port_pattern uri: ${test.uri} predicates: - name: Host