Extracts variables from Host Route Predicate.
fixes gh-706
This commit is contained in:
@@ -146,11 +146,15 @@ spring:
|
||||
- id: host_route
|
||||
uri: http://example.org
|
||||
predicates:
|
||||
- Host=**.somehost.org
|
||||
- Host={sub}.somehost.org
|
||||
----
|
||||
|
||||
Ant patterns work as well, such as `**.somehost.org`.
|
||||
|
||||
This route would match if the request has a `Host` header has the value `www.somehost.org` or `beta.somehost.org`.
|
||||
|
||||
This predicate extracts the URI template variables (like `sub` defined in the example above) as a map of names and values and places it in the `ServerWebExchange.getAttributes()` with a key defined in `ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE`. Those values are then available for use by <<gateway-route-filters,GatewayFilter Factories>>
|
||||
|
||||
|
||||
=== Method Route Predicate Factory
|
||||
The Method Route Predicate Factory takes one parameter: the HTTP method to match.
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.web.util.UriTemplate;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.getPathMatchVariables;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.getUriTemplateVariables;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -54,7 +54,7 @@ public class SetPathGatewayFilterFactory extends AbstractGatewayFilterFactory<Se
|
||||
ServerHttpRequest req = exchange.getRequest();
|
||||
addOriginalRequestUrl(exchange, req.getURI());
|
||||
|
||||
Map<String, String> uriVariables = getPathMatchVariables(exchange);
|
||||
Map<String, String> uriVariables = getUriTemplateVariables(exchange);
|
||||
|
||||
URI uri = uriTemplate.expand(uriVariables);
|
||||
String newPath = uri.getRawPath();
|
||||
|
||||
@@ -19,8 +19,10 @@ package org.springframework.cloud.gateway.handler.predicate;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
@@ -51,7 +53,12 @@ public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory<Hos
|
||||
public Predicate<ServerWebExchange> apply(Config config) {
|
||||
return exchange -> {
|
||||
String host = exchange.getRequest().getHeaders().getFirst("Host");
|
||||
return this.pathMatcher.match(config.getPattern(), host);
|
||||
boolean match = this.pathMatcher.match(config.getPattern(), host);
|
||||
if (match) {
|
||||
Map<String, String> variables = this.pathMatcher.extractUriTemplateVariables(config.getPattern(), host);
|
||||
ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);
|
||||
}
|
||||
return match;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.web.util.pattern.PathPattern;
|
||||
import org.springframework.web.util.pattern.PathPattern.PathMatchInfo;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.putUriTemplateVariables;
|
||||
import static org.springframework.http.server.PathContainer.parsePath;
|
||||
|
||||
/**
|
||||
@@ -69,8 +69,8 @@ public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<Pat
|
||||
boolean match = config.pathPattern.matches(path);
|
||||
traceMatch("Pattern", config.pathPattern.getPatternString(), path, match);
|
||||
if (match) {
|
||||
PathMatchInfo uriTemplateVariables = config.pathPattern.matchAndExtract(path);
|
||||
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
PathMatchInfo pathMatchInfo = config.pathPattern.matchAndExtract(path);
|
||||
putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
|
||||
}
|
||||
return match;
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
package org.springframework.cloud.gateway.support;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -32,7 +32,6 @@ import org.springframework.cloud.gateway.handler.AsyncPredicate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -127,12 +126,20 @@ public class ServerWebExchangeUtils {
|
||||
return t -> Mono.just(predicate.test(t));
|
||||
}
|
||||
|
||||
public static Map<String, String> getPathMatchVariables(ServerWebExchange exchange) {
|
||||
PathPattern.PathMatchInfo variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (variables != null) {
|
||||
return variables.getUriVariables();
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void putUriTemplateVariables(ServerWebExchange exchange, Map<String, String> uriVariables) {
|
||||
if (exchange.getAttributes().containsKey(URI_TEMPLATE_VARIABLES_ATTRIBUTE)) {
|
||||
Map<String, Object> existingVariables = (Map<String, Object>) exchange.getAttributes().get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
HashMap<String, Object> newVariables = new HashMap<>();
|
||||
newVariables.putAll(existingVariables);
|
||||
newVariables.putAll(uriVariables);
|
||||
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, newVariables);
|
||||
} else {
|
||||
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
|
||||
}
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public static Map<String, String> getUriTemplateVariables(ServerWebExchange exchange) {
|
||||
return exchange.getAttributeOrDefault(URI_TEMPLATE_VARIABLES_ATTRIBUTE, new HashMap<>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,18 @@ public class SetPathGatewayFilterFactoryIntegrationTests extends BaseWebClientTe
|
||||
.uri("/foo/get")
|
||||
.header("Host", "www.setpath.org")
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, "set_path_test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPathViaHostFilterWork() {
|
||||
testClient.get()
|
||||
.uri("/")
|
||||
.header("Host", "get.setpathhost.org")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, "set_path_host_test");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
|
||||
@@ -17,30 +17,25 @@
|
||||
|
||||
package org.springframework.cloud.gateway.filter.factory;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.web.util.pattern.PathPattern.PathMatchInfo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -89,15 +84,7 @@ public class SetPathGatewayFilterFactoryTests {
|
||||
.build();
|
||||
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
|
||||
try {
|
||||
Constructor<PathMatchInfo> constructor = ReflectionUtils.accessibleConstructor(PathMatchInfo.class, Map.class, Map.class);
|
||||
constructor.setAccessible(true);
|
||||
PathMatchInfo pathMatchInfo = constructor.newInstance(variables, Collections.emptyMap());
|
||||
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathMatchInfo);
|
||||
} catch (Exception e) {
|
||||
ReflectionUtils.rethrowRuntimeException(e);
|
||||
}
|
||||
ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);
|
||||
|
||||
GatewayFilterChain filterChain = mock(GatewayFilterChain.class);
|
||||
|
||||
|
||||
@@ -196,6 +196,14 @@ spring:
|
||||
filters:
|
||||
- SetPath=/{segment}
|
||||
|
||||
# =====================================
|
||||
- id: set_path_host_test
|
||||
uri: ${test.uri}
|
||||
predicates:
|
||||
- Host={subdomain}.setpathhost.org
|
||||
filters:
|
||||
- SetPath=/{subdomain}
|
||||
|
||||
# =====================================
|
||||
- id: strip_prefix_test
|
||||
uri: ${test.uri}
|
||||
|
||||
Reference in New Issue
Block a user