Make host ignoring port opt in.

This makes gh-3037 opt in by setting spring.cloud.gateway.predicate.host.include-port=false

Fixes gh-3190
This commit is contained in:
sgibb
2023-12-21 11:17:03 -05:00
parent ed637f5497
commit 09ecf0a245
5 changed files with 66 additions and 22 deletions

View File

@@ -442,8 +442,9 @@ public class GatewayAutoConfiguration {
@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

View File

@@ -35,16 +35,27 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory<HostRoutePredicateFactory.Config> {
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<String> shortcutFieldOrder() {
return Collections.singletonList("patterns");
@@ -60,25 +71,35 @@ public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory<Hos
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;
}
}
if (match != null) {
Map<String, String> variables = pathMatcher.extractUriTemplateVariables(match, host);
ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);
return true;
}
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;
}
}
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<String, String> variables = pathMatcher.extractUriTemplateVariables(match, host);
ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);
return true;
}
return false;
}

View File

@@ -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"
}
]
}

View File

@@ -21,6 +21,7 @@ import java.util.function.Predicate;
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 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@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 class HostRoutePredicateFactoryTests extends BaseWebClientTests {
@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

View File

@@ -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