Allows multiple patterns in host route predicate.
Each pattern is checked if it matches in order. fixes gh-589
This commit is contained in:
@@ -134,7 +134,7 @@ spring:
|
||||
This route matches if the request has a header named `X-Request-Id` whos value matches the `\d+` regular expression (has a value of one or more digits).
|
||||
|
||||
=== Host Route Predicate Factory
|
||||
The Host Route Predicate Factory takes one parameter: the host name pattern. The pattern is an Ant style pattern with `.` as the separator. This predicates matches the `Host` header that matches the pattern.
|
||||
The Host Route Predicate Factory takes one parameter: a list of host name patterns. The pattern is an Ant style pattern with `.` as the separator. This predicates matches the `Host` header that matches the pattern.
|
||||
|
||||
.application.yml
|
||||
[source,yaml]
|
||||
@@ -146,10 +146,10 @@ spring:
|
||||
- id: host_route
|
||||
uri: http://example.org
|
||||
predicates:
|
||||
- Host=**.somehost.org
|
||||
- Host=**.somehost.org,**.anotherhost.org
|
||||
----
|
||||
|
||||
This route would match if the request has a `Host` header has the value `www.somehost.org` or `beta.somehost.org`.
|
||||
This route would match if the request has a `Host` header has the value `www.somehost.org` or `beta.somehost.org` or `www.anotherhost.org`.
|
||||
|
||||
|
||||
=== Method Route Predicate Factory
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
|
||||
package org.springframework.cloud.gateway.handler.predicate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
@@ -44,34 +46,54 @@ public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory<Hos
|
||||
|
||||
@Override
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Collections.singletonList(PATTERN_KEY);
|
||||
return Collections.singletonList("patterns");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortcutType shortcutType() {
|
||||
return ShortcutType.GATHER_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> apply(Config config) {
|
||||
return exchange -> {
|
||||
String host = exchange.getRequest().getHeaders().getFirst("Host");
|
||||
return this.pathMatcher.match(config.getPattern(), host);
|
||||
return config.getPatterns().stream()
|
||||
.anyMatch(pattern -> this.pathMatcher.match(pattern, host));
|
||||
};
|
||||
}
|
||||
|
||||
@Validated
|
||||
public static class Config {
|
||||
private String pattern;
|
||||
private List<String> patterns = new ArrayList<>();
|
||||
|
||||
@Deprecated
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
if (!CollectionUtils.isEmpty(this.patterns)) {
|
||||
return patterns.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Config setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
this.patterns = new ArrayList<>();
|
||||
this.patterns.add(pattern);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getPatterns() {
|
||||
return patterns;
|
||||
}
|
||||
|
||||
public void setPatterns(List<String> patterns) {
|
||||
this.patterns = patterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this)
|
||||
.append("pattern", pattern)
|
||||
.append("patterns", patterns)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.gateway.route.builder;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.cloud.gateway.handler.AsyncPredicate;
|
||||
@@ -134,9 +135,9 @@ public class PredicateSpec extends UriSpec {
|
||||
* @param pattern the pattern to check against. The pattern is an Ant style pattern with {@code .} as a separator
|
||||
* @return a {@link BooleanSpec} to be used to add logical operators
|
||||
*/
|
||||
public BooleanSpec host(String pattern) {
|
||||
public BooleanSpec host(String... pattern) {
|
||||
return asyncPredicate(getBean(HostRoutePredicateFactory.class)
|
||||
.applyAsync(c-> c.setPattern(pattern)));
|
||||
.applyAsync(c-> c.setPatterns(Arrays.asList(pattern))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,11 +19,15 @@ package org.springframework.cloud.gateway.handler.predicate;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||
import org.springframework.cloud.gateway.test.BaseWebClientTests;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -37,18 +41,57 @@ public class HostRoutePredicateFactoryTests extends BaseWebClientTests {
|
||||
|
||||
@Test
|
||||
public void hostRouteWorks() {
|
||||
expectHostRoute("www.example.org", "host_example_to_httpbin");
|
||||
}
|
||||
|
||||
public void expectHostRoute(String host, String routeId) {
|
||||
testClient.get()
|
||||
.uri("/get")
|
||||
.header("Host", "www.example.org")
|
||||
.header("Host", host)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals(HANDLER_MAPPER_HEADER, RoutePredicateHandlerMapping.class.getSimpleName())
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, "host_example_to_httpbin");
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, routeId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostRouteBackwardsCompatiblePatternWorks() {
|
||||
expectHostRoute("www.hostpatternarg.org", "host_backwards_compatible_test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostRouteBackwardsCompatibleShortcutWorks() {
|
||||
expectHostRoute("www.hostpatternshortcut.org", "host_backwards_compatible_shortcut_test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulitHostRouteWorks() {
|
||||
expectHostRoute("www.hostmulti1.org", "host_multi_test");
|
||||
expectHostRoute("www.hostmulti2.org", "host_multi_test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulitHostRouteDslWorks() {
|
||||
expectHostRoute("www.hostmultidsl1.org", "host_multi_dsl");
|
||||
expectHostRoute("www.hostmultidsl2.org", "host_multi_dsl");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@SpringBootConfiguration
|
||||
@Import(DefaultTestConfig.class)
|
||||
public static class TestConfig { }
|
||||
public static class TestConfig {
|
||||
|
||||
@Value("${test.uri}")
|
||||
String uri;
|
||||
|
||||
@Bean
|
||||
public RouteLocator testRouteLocator(RouteLocatorBuilder builder) {
|
||||
return builder.routes()
|
||||
.route("host_multi_dsl", r -> r.host("**.hostmultidsl1.org", "**.hostmultidsl2.org")
|
||||
.filters(f -> f.prefixPath("/httpbin"))
|
||||
.uri(uri))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,6 +81,26 @@ spring:
|
||||
predicates:
|
||||
- Host=**.forward.org
|
||||
|
||||
# =====================================
|
||||
- id: host_backwards_compatible_test
|
||||
uri: ${test.uri}
|
||||
predicates:
|
||||
- name: Host
|
||||
args:
|
||||
pattern: '**.hostpatternarg.org'
|
||||
|
||||
# =====================================
|
||||
- id: host_backwards_compatible_shortcut_test
|
||||
uri: ${test.uri}
|
||||
predicates:
|
||||
- Host=**.hostpatternshortcut.org
|
||||
|
||||
# =====================================
|
||||
- id: host_multi_test
|
||||
uri: ${test.uri}
|
||||
predicates:
|
||||
- Host=**.hostmulti1.org,**.hostmulti2.org
|
||||
|
||||
# =====================================
|
||||
- id: hystrix_failure_test
|
||||
uri: ${test.uri}
|
||||
|
||||
Reference in New Issue
Block a user