diff --git a/docs/src/main/asciidoc/spring-cloud-gateway.adoc b/docs/src/main/asciidoc/spring-cloud-gateway.adoc index 8c8fb827..27c22401 100644 --- a/docs/src/main/asciidoc/spring-cloud-gateway.adoc +++ b/docs/src/main/asciidoc/spring-cloud-gateway.adoc @@ -29,22 +29,22 @@ TODO: document the meaning of terms to follow, like Route, Predicate and Filter TODO: give an overview of how the gateway works with maybe a ascii diagram -[[gateway-route-predicates]] -== Route Predicates +[[gateway-request-predicates-factories]] +== Request Predicate Factories -Spring Cloud Gateway matches routes as part of the Spring WebFlux `HandlerMapping` infrastructure. Spring Cloud Gateway includes many built-in Route Predicates. All of these predicates match on different attributes of the HTTP request. Multiple Route Predicates can be combined and are combined via logical `and`. +Spring Cloud Gateway matches routes as part of the Spring WebFlux `HandlerMapping` infrastructure. Spring Cloud Gateway includes many built-in Request Predicate Factorys. All of these predicates match on different attributes of the HTTP request. Multiple Request Predicate Factorys can be combined and are combined via logical `and`. -=== After Route Predicate -TODO: document After Route Predicate +=== After Request Predicate Factory +TODO: document After Request Predicate Factory -=== Before Route Predicate -TODO: document Before Route Predicate +=== Before Request Predicate Factory +TODO: document Before Request Predicate Factory -=== Between Route Predicate -TODO: document Between Route Predicate +=== Between Request Predicate Factory +TODO: document Between Request Predicate Factory -=== Cookie Route Predicate -The Cookie Route Predicate takes two parameters, the cookie name and a regular expression. This predicate matches cookies that have the given name and the value matches the regular expression. +=== Cookie Request Predicate Factory +The Cookie Request Predicate Factory takes two parameters, the cookie name and a regular expression. This predicate matches cookies that have the given name and the value matches the regular expression. .application.yml [source,yaml] @@ -62,8 +62,8 @@ spring: This route matches the request has a cookie named `chocolate` who's value matches the `ch.p` regular expression. -=== Header Route Predicate -The Header Route Predicate takes two parameters, the header name and a regular expression. This predicate matches with a header that has the given name and the value matches the regular expression. +=== Header Request Predicate Factory +The Header Request Predicate Factory takes two parameters, the header name and a regular expression. This predicate matches with a header that has the given name and the value matches the regular expression. .application.yml [source,yaml] @@ -81,8 +81,8 @@ 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 -The Host Route Predicate 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. +=== Host Request Predicate Factory +The Host Request 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. .application.yml [source,yaml] @@ -101,8 +101,8 @@ spring: This route would match if the request has a `Host` header has the value `www.somehost.org` or `beta.somehost.org`. -=== Method Route Predicate -The Method Route Predicate takes one parameter: the HTTP method to match. +=== Method Request Predicate Factory +The Method Request Predicate Factory takes one parameter: the HTTP method to match. .application.yml [source,yaml] @@ -120,8 +120,8 @@ spring: This route would match if the request method was a `GET`. -=== Path Route Predicate -The Path Route Predicate takes one parameter: a Spring `PathMatcher` pattern. +=== Path Request Predicate Factory +The Path Request Predicate Factory takes one parameter: a Spring `PathMatcher` pattern. .application.yml [source,yaml] @@ -141,11 +141,11 @@ This route would match if the request path was, for example: `/foo/1` or `/foo/b This predicate extracts the URI template variables (like `segment` defined in the example above) as a map of names and values and places it in the `ServerWebExchange.getAttributes()` with a key defined in `PathRoutePredicate.URL_PREDICATE_VARS_ATTR`. Those values are then available for use by <> -=== Query Route Predicate -TODO: document Query Route Predicate +=== Query Request Predicate Factory +TODO: document Query Request Predicate Factory -=== RemoteAddr Route Predicate -TODO: document RemoteAddr Route Predicate +=== RemoteAddr Request Predicate Factory +TODO: document RemoteAddr Request Predicate Factory [[gateway-route-filters]] == Route Filters @@ -210,9 +210,9 @@ TODO: document the `/gateway` actuator endpoint TODO: overview of writing custom integrations -=== Writing Custom Route Predicates +=== Writing Custom Request Predicate Factorys -TODO: document writing Custom Route Predicates +TODO: document writing Custom Request Predicate Factorys === Writing Custom Route Filters diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index 194d3736..58f89126 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -27,18 +27,18 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.gateway.actuate.GatewayEndpoint; -import org.springframework.cloud.gateway.filter.route.PrefixPathRouteFilter; import org.springframework.cloud.gateway.api.RouteLocator; import org.springframework.cloud.gateway.api.RouteWriter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; -import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter; import org.springframework.cloud.gateway.filter.NettyRoutingFilter; +import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter; import org.springframework.cloud.gateway.filter.WriteResponseFilter; import org.springframework.cloud.gateway.filter.route.AddRequestHeaderRouteFilter; import org.springframework.cloud.gateway.filter.route.AddRequestParameterRouteFilter; import org.springframework.cloud.gateway.filter.route.AddResponseHeaderRouteFilter; import org.springframework.cloud.gateway.filter.route.HystrixRouteFilter; +import org.springframework.cloud.gateway.filter.route.PrefixPathRouteFilter; import org.springframework.cloud.gateway.filter.route.RedirectToRouteFilter; import org.springframework.cloud.gateway.filter.route.RemoveNonProxyHeadersRouteFilter; import org.springframework.cloud.gateway.filter.route.RemoveRequestHeaderRouteFilter; @@ -51,19 +51,19 @@ import org.springframework.cloud.gateway.filter.route.SetPathRouteFilter; import org.springframework.cloud.gateway.filter.route.SetResponseHeaderRouteFilter; import org.springframework.cloud.gateway.filter.route.SetStatusRouteFilter; import org.springframework.cloud.gateway.handler.FilteringWebHandler; -import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; import org.springframework.cloud.gateway.handler.NettyRoutingWebHandler; -import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicate; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicate; +import org.springframework.cloud.gateway.handler.RequestPredicateHandlerMapping; +import org.springframework.cloud.gateway.handler.predicate.AfterRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.BeforeRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.CookieRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.HeaderRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.HostRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.MethodRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.PathRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.QueryRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRequestPredicateFactory; +import org.springframework.cloud.gateway.handler.predicate.RequestPredicateFactory; import org.springframework.cloud.gateway.support.CachingRouteLocator; import org.springframework.cloud.gateway.support.InMemoryRouteRepository; import org.springframework.context.annotation.Bean; @@ -119,10 +119,10 @@ public class GatewayAutoConfiguration { } @Bean - public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, - Map predicates, - RouteLocator routeLocator) { - return new RoutePredicateHandlerMapping(webHandler, predicates, routeLocator); + public RequestPredicateHandlerMapping requestPredicateHandlerMapping(FilteringWebHandler webHandler, + Map predicates, + RouteLocator routeLocator) { + return new RequestPredicateHandlerMapping(webHandler, predicates, routeLocator); } // ConfigurationProperty beans @@ -159,56 +159,56 @@ public class GatewayAutoConfiguration { return new WriteResponseFilter(); } - // Predicate beans + // Request Predicate beans - @Bean(name = "AfterRoutePredicate") - public AfterRoutePredicate afterRoutePredicate() { - return new AfterRoutePredicate(); + @Bean(name = "AfterRequestPredicateFactory") + public AfterRequestPredicateFactory afterRequestPredicateFactory() { + return new AfterRequestPredicateFactory(); } - @Bean(name = "BeforeRoutePredicate") - public BeforeRoutePredicate beforeRoutePredicate() { - return new BeforeRoutePredicate(); + @Bean(name = "BeforeRequestPredicateFactory") + public BeforeRequestPredicateFactory beforeRequestPredicateFactory() { + return new BeforeRequestPredicateFactory(); } - @Bean(name = "BetweenRoutePredicate") - public BetweenRoutePredicate betweenRoutePredicate() { - return new BetweenRoutePredicate(); + @Bean(name = "BetweenRequestPredicateFactory") + public BetweenRequestPredicateFactory betweenRequestPredicateFactory() { + return new BetweenRequestPredicateFactory(); } - @Bean(name = "CookieRoutePredicate") - public CookieRoutePredicate cookieRoutePredicate() { - return new CookieRoutePredicate(); + @Bean(name = "CookieRequestPredicateFactory") + public CookieRequestPredicateFactory cookieRequestPredicateFactory() { + return new CookieRequestPredicateFactory(); } - @Bean(name = "HeaderRoutePredicate") - public HeaderRoutePredicate headerRoutePredicate() { - return new HeaderRoutePredicate(); + @Bean(name = "HeaderRequestPredicateFactory") + public HeaderRequestPredicateFactory headerRequestPredicateFactory() { + return new HeaderRequestPredicateFactory(); } - @Bean(name = "HostRoutePredicate") - public HostRoutePredicate hostRoutePredicate() { - return new HostRoutePredicate(); + @Bean(name = "HostRequestPredicateFactory") + public HostRequestPredicateFactory hostRequestPredicateFactory() { + return new HostRequestPredicateFactory(); } - @Bean(name = "MethodRoutePredicate") - public MethodRoutePredicate methodRoutePredicate() { - return new MethodRoutePredicate(); + @Bean(name = "MethodRequestPredicateFactory") + public MethodRequestPredicateFactory methodRequestPredicateFactory() { + return new MethodRequestPredicateFactory(); } - @Bean(name = "PathRoutePredicate") - public PathRoutePredicate pathRoutePredicate() { - return new PathRoutePredicate(); + @Bean(name = "PathRequestPredicateFactory") + public PathRequestPredicateFactory pathRequestPredicateFactory() { + return new PathRequestPredicateFactory(); } - @Bean(name = "QueryRoutePredicate") - public QueryRoutePredicate queryRoutePredicate() { - return new QueryRoutePredicate(); + @Bean(name = "QueryRequestPredicateFactory") + public QueryRequestPredicateFactory queryRequestPredicateFactory() { + return new QueryRequestPredicateFactory(); } - @Bean(name = "RemoteAddrRoutePredicate") - public RemoteAddrRoutePredicate remoteAddrRoutePredicate() { - return new RemoteAddrRoutePredicate(); + @Bean(name = "RemoteAddrRequestPredicateFactory") + public RemoteAddrRequestPredicateFactory remoteAddrRequestPredicateFactory() { + return new RemoteAddrRequestPredicateFactory(); } // Filter Factory beans diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteLocator.java index c22c3a00..69526c52 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteLocator.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteLocator.java @@ -20,12 +20,12 @@ package org.springframework.cloud.gateway.discovery; import java.net.URI; import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.gateway.api.RouteLocator; +import org.springframework.cloud.gateway.filter.route.RewritePathRouteFilter; +import org.springframework.cloud.gateway.handler.predicate.PathRequestPredicateFactory; import org.springframework.cloud.gateway.model.FilterDefinition; import org.springframework.cloud.gateway.model.PredicateDefinition; import org.springframework.cloud.gateway.model.Route; -import org.springframework.cloud.gateway.api.RouteLocator; -import org.springframework.cloud.gateway.filter.route.RewritePathRouteFilter; -import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicate; import static org.springframework.cloud.gateway.support.NameUtils.normalizeFilterName; import static org.springframework.cloud.gateway.support.NameUtils.normalizePredicateName; @@ -56,7 +56,7 @@ public class DiscoveryClientRouteLocator implements RouteLocator { // add a predicate that matches the url at /serviceId/** PredicateDefinition predicate = new PredicateDefinition(); - predicate.setName(normalizePredicateName(PathRoutePredicate.class)); + predicate.setName(normalizePredicateName(PathRequestPredicateFactory.class)); predicate.setArgs("/" + serviceId + "/**"); route.getPredicates().add(predicate); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilter.java index e9811f77..928f6979 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilter.java @@ -20,12 +20,12 @@ package org.springframework.cloud.gateway.filter.route; import java.net.URI; import java.util.Map; -import org.springframework.web.server.WebFilter; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.WebFilter; import org.springframework.web.util.UriTemplate; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.getAttribute; -import static org.springframework.cloud.gateway.handler.predicate.PathRoutePredicate.URL_PREDICATE_VARS_ATTR; +import static org.springframework.web.reactive.function.server.RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE; /** * @author Spencer Gibb @@ -39,7 +39,7 @@ public class SetPathRouteFilter implements RouteFilter { UriTemplate uriTemplate = new UriTemplate(args[0]); return (exchange, chain) -> { - Map variables = getAttribute(exchange, URL_PREDICATE_VARS_ATTR, Map.class); + Map variables = getAttribute(exchange, URI_TEMPLATE_VARIABLES_ATTRIBUTE, Map.class); ServerHttpRequest req = exchange.getRequest(); URI uri = uriTemplate.expand(variables); String newPath = uri.getPath(); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMapping.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RequestPredicateHandlerMapping.java similarity index 75% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMapping.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RequestPredicateHandlerMapping.java index 64c7331c..868266ed 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMapping.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RequestPredicateHandlerMapping.java @@ -24,12 +24,13 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -import java.util.function.Predicate; import org.springframework.cloud.gateway.api.RouteLocator; +import org.springframework.cloud.gateway.handler.predicate.RequestPredicateFactory; import org.springframework.cloud.gateway.model.Route; import org.springframework.cloud.gateway.model.PredicateDefinition; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicate; +import org.springframework.web.reactive.function.server.PublicDefaultServerRequest; +import org.springframework.web.reactive.function.server.RequestPredicate; import org.springframework.web.reactive.handler.AbstractHandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebHandler; @@ -42,29 +43,29 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G /** * @author Spencer Gibb */ -public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { +public class RequestPredicateHandlerMapping extends AbstractHandlerMapping { private final RouteLocator routeLocator; private final WebHandler webHandler; - private final Map routePredicates = new LinkedHashMap<>(); + private final Map routePredicates = new LinkedHashMap<>(); //TODO: define semeantics for refresh (ie clearing and recalculating combinedPredicates) - private final Map> combinedPredicates = new ConcurrentHashMap<>(); + private final Map combinedPredicates = new ConcurrentHashMap<>(); - public RoutePredicateHandlerMapping(WebHandler webHandler, Map routePredicates, - RouteLocator routeLocator) { + public RequestPredicateHandlerMapping(WebHandler webHandler, Map routePredicates, + RouteLocator routeLocator) { this.webHandler = webHandler; this.routeLocator = routeLocator; routePredicates.forEach((name, factory) -> { String key = normalizeName(name); if (this.routePredicates.containsKey(key)) { - this.logger.warn("A RoutePredicate named "+ key + this.logger.warn("A RequestPredicateFactory named "+ key + " already exists, class: " + this.routePredicates.get(key) + ". It will be overwritten."); } this.routePredicates.put(key, factory); if (logger.isInfoEnabled()) { - logger.info("Loaded RoutePredicate [" + key + "]"); + logger.info("Loaded RequestPredicateFactory [" + key + "]"); } }); @@ -72,7 +73,7 @@ public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { } private String normalizeName(String name) { - return name.replace(RoutePredicate.class.getSimpleName(), ""); + return name.replace(RequestPredicateFactory.class.getSimpleName(), ""); } @Override @@ -109,9 +110,9 @@ public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { protected Mono lookupRoute(ServerWebExchange exchange) { return this.routeLocator.getRoutes() - //TODO: cache predicate - .map(route -> getRouteCombinedPredicates(route)) - .filter(rcp -> rcp.combinedPredicate.test(exchange)) + .map(this::getRouteCombinedPredicates) + //TODO: fix PublicDefaultServerRequest? + .filter(rcp -> rcp.combinedPredicate.test(new PublicDefaultServerRequest(exchange))) .next() //TODO: error handling .map(rcp -> { @@ -129,7 +130,7 @@ public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { } private RouteCombinedPredicates getRouteCombinedPredicates(Route route) { - Predicate predicate = this.combinedPredicates + RequestPredicate predicate = this.combinedPredicates .computeIfAbsent(route.getId(), k -> combinePredicates(route)); return new RouteCombinedPredicates(route, predicate); @@ -137,31 +138,31 @@ public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { private class RouteCombinedPredicates { private Route route; - private Predicate combinedPredicate; + private RequestPredicate combinedPredicate; - public RouteCombinedPredicates(Route route, Predicate combinedPredicate) { + public RouteCombinedPredicates(Route route, RequestPredicate combinedPredicate) { this.route = route; this.combinedPredicate = combinedPredicate; } } - private Predicate combinePredicates(Route route) { + private RequestPredicate combinePredicates(Route route) { List predicates = route.getPredicates(); - Predicate predicate = lookup(route, predicates.get(0)); + RequestPredicate predicate = lookup(route, predicates.get(0)); for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) { - Predicate found = lookup(route, andPredicate); + RequestPredicate found = lookup(route, andPredicate); predicate = predicate.and(found); } return predicate; } - private Predicate lookup(Route route, PredicateDefinition predicate) { - RoutePredicate found = this.routePredicates.get(predicate.getName()); + private RequestPredicate lookup(Route route, PredicateDefinition predicate) { + RequestPredicateFactory found = this.routePredicates.get(predicate.getName()); if (found == null) { - throw new IllegalArgumentException("Unable to find RoutePredicate with name " + predicate.getName()); + throw new IllegalArgumentException("Unable to find RequestPredicateFactory with name " + predicate.getName()); } if (logger.isDebugEnabled()) { List args; diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRequestPredicateFactory.java similarity index 78% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRequestPredicateFactory.java index 901df691..a870664c 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRequestPredicateFactory.java @@ -18,23 +18,22 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.ZonedDateTime; -import java.util.function.Predicate; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicate.parseZonedDateTime; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactory.parseZonedDateTime; /** * @author Spencer Gibb */ -public class AfterRoutePredicate implements RoutePredicate { +public class AfterRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(1, args); final ZonedDateTime dateTime = parseZonedDateTime(args[0]); - return exchange -> { + return request -> { final ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(dateTime); }; diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRequestPredicateFactory.java similarity index 78% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRequestPredicateFactory.java index 2948519c..f5cdf203 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRequestPredicateFactory.java @@ -18,23 +18,22 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.ZonedDateTime; -import java.util.function.Predicate; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicate.parseZonedDateTime; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactory.parseZonedDateTime; /** * @author Spencer Gibb */ -public class BeforeRoutePredicate implements RoutePredicate { +public class BeforeRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(1, args); final ZonedDateTime dateTime = parseZonedDateTime(args[0]); - return exchange -> { + return request -> { final ZonedDateTime now = ZonedDateTime.now(); return now.isBefore(dateTime); }; diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRequestPredicateFactory.java similarity index 87% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRequestPredicateFactory.java index 19b12a3a..e7affec1 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRequestPredicateFactory.java @@ -20,18 +20,17 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.Instant; import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.util.function.Predicate; import org.springframework.util.Assert; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; /** * @author Spencer Gibb */ -public class BetweenRoutePredicate implements RoutePredicate { +public class BetweenRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(2, args); //TODO: is ZonedDateTime the right thing to use? @@ -39,7 +38,7 @@ public class BetweenRoutePredicate implements RoutePredicate { final ZonedDateTime dateTime2 = parseZonedDateTime(args[1]); Assert.isTrue(dateTime1.isBefore(dateTime2), args[0] + " must be before " + args[1]); - return exchange -> { + return request -> { final ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(dateTime1) && now.isBefore(dateTime2); }; diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRequestPredicateFactory.java similarity index 68% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRequestPredicateFactory.java index cbdb5e5a..397b3bc8 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRequestPredicateFactory.java @@ -18,24 +18,26 @@ package org.springframework.cloud.gateway.handler.predicate; import java.util.List; -import java.util.function.Predicate; import org.springframework.http.HttpCookie; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.PublicDefaultServerRequest; +import org.springframework.web.reactive.function.server.RequestPredicate; /** * @author Spencer Gibb */ -public class CookieRoutePredicate implements RoutePredicate { +public class CookieRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(2, args); String name = args[0]; String regexp = args[1]; - return exchange -> { - List cookies = exchange.getRequest().getCookies().get(name); + return request -> { + //TODO: bad cast? + PublicDefaultServerRequest req = (PublicDefaultServerRequest) request; + List cookies = req.getCookies().get(name); for (HttpCookie cookie : cookies) { if (cookie.getValue().matches(regexp)) { return true; diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRequestPredicateFactory.java similarity index 70% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRequestPredicateFactory.java index 072388b8..25558191 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRequestPredicateFactory.java @@ -18,30 +18,29 @@ package org.springframework.cloud.gateway.handler.predicate; import java.util.List; -import java.util.function.Predicate; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RequestPredicates; /** * @author Spencer Gibb */ -public class HeaderRoutePredicate implements RoutePredicate { +public class HeaderRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(2, args); String header = args[0]; String regexp = args[1]; - return exchange -> { - - List values = exchange.getRequest().getHeaders().get(header); + return RequestPredicates.headers(headers -> { + List values = headers.asHttpHeaders().get(header); for (String value : values) { if (value.matches(regexp)) { return true; } } return false; - }; + }); } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRequestPredicateFactory.java similarity index 73% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRequestPredicateFactory.java index 2dfb4d16..4757df42 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRequestPredicateFactory.java @@ -17,16 +17,15 @@ package org.springframework.cloud.gateway.handler.predicate; -import java.util.function.Predicate; - import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RequestPredicates; /** * @author Spencer Gibb */ -public class HostRoutePredicate implements RoutePredicate { +public class HostRequestPredicateFactory implements RequestPredicateFactory { private PathMatcher pathMatcher = new AntPathMatcher("."); @@ -35,13 +34,13 @@ public class HostRoutePredicate implements RoutePredicate { } @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(1, args); String pattern = args[0]; - return exchange -> { - String host = exchange.getRequest().getHeaders().getFirst("Host"); + return RequestPredicates.headers(headers -> { + String host = headers.asHttpHeaders().getFirst("Host"); return this.pathMatcher.match(pattern, host); - }; + }); } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRequestPredicateFactory.java similarity index 70% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRequestPredicateFactory.java index bb8452a2..51d20de1 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRequestPredicateFactory.java @@ -17,23 +17,19 @@ package org.springframework.cloud.gateway.handler.predicate; -import java.util.function.Predicate; - import org.springframework.http.HttpMethod; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RequestPredicates; /** * @author Spencer Gibb */ -public class MethodRoutePredicate implements RoutePredicate { +public class MethodRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(1, args); String method = args[0]; - return exchange -> { - HttpMethod requestMethod = exchange.getRequest().getMethod(); - return requestMethod.matches(method); - }; + return RequestPredicates.method(HttpMethod.resolve(method)); } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRequestPredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRequestPredicateFactory.java new file mode 100644 index 00000000..ffb2e62d --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRequestPredicateFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.springframework.cloud.gateway.handler.predicate; + +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RequestPredicates; + +/** + * @author Spencer Gibb + */ +public class PathRequestPredicateFactory implements RequestPredicateFactory { + + @Override + public RequestPredicate apply(String... args) { + validate(1, args); + String pattern = args[0]; + + //TODO: support custom PathPatternParser + return RequestPredicates.path(pattern); + } +} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicate.java deleted file mode 100644 index 574fb9fc..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.springframework.cloud.gateway.handler.predicate; - -import java.util.Map; -import java.util.function.Predicate; - -import org.springframework.util.PathMatcher; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.support.HttpRequestPathHelper; -import org.springframework.web.util.ParsingPathMatcher; - -/** - * @author Spencer Gibb - */ -public class PathRoutePredicate implements RoutePredicate { - - public static final String URL_PREDICATE_VARS_ATTR = "urlPredicateVars"; - - private PathMatcher pathMatcher = new ParsingPathMatcher(); - private HttpRequestPathHelper pathHelper = new HttpRequestPathHelper(); - - public PathMatcher getPathMatcher() { - return pathMatcher; - } - - public void setPathMatcher(PathMatcher pathMatcher) { - this.pathMatcher = pathMatcher; - } - - public HttpRequestPathHelper getPathHelper() { - return pathHelper; - } - - public void setPathHelper(HttpRequestPathHelper pathHelper) { - this.pathHelper = pathHelper; - } - - @Override - public Predicate apply(String... args) { - validate(1, args); - String pattern = args[0]; - - return exchange -> { - String lookupPath = getPathHelper().getLookupPathForRequest(exchange); - boolean match = getPathMatcher().match(pattern, lookupPath); - if (match) { - Map variables = getPathMatcher().extractUriTemplateVariables(pattern, lookupPath); - exchange.getAttributes().put(URL_PREDICATE_VARS_ATTR, variables); - } - return match; - //TODO: support trailingSlashMatch - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRequestPredicateFactory.java similarity index 51% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRequestPredicateFactory.java index 29286f26..a9b46003 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRequestPredicateFactory.java @@ -17,36 +17,30 @@ package org.springframework.cloud.gateway.handler.predicate; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.PublicDefaultServerRequest; +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RequestPredicates; /** * @author Spencer Gibb */ -public class QueryRoutePredicate implements RoutePredicate { +public class QueryRequestPredicateFactory implements RequestPredicateFactory { @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(1, args); String param = args[0]; - return exchange -> { - if (args.length < 2) { - // check existence of header - return exchange.getRequest().getQueryParams().containsKey(param); - } + if (args.length < 2) { + return req -> { + //TODO: ServerRequest support for query params with no value + PublicDefaultServerRequest request = (PublicDefaultServerRequest) req; + return request.getExchange().getRequest().getQueryParams().containsKey(param); + }; + } - String regexp = args[1]; + String regexp = args[1]; - List values = exchange.getRequest().getQueryParams().get(param); - for (String value : values) { - if (value.matches(regexp)) { - return true; - } - } - return false; - }; + return RequestPredicates.queryParam(param, value -> value.matches(regexp)); } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRequestPredicateFactory.java similarity index 63% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRequestPredicateFactory.java index 537585e6..493ec30f 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRequestPredicateFactory.java @@ -20,23 +20,23 @@ package org.springframework.cloud.gateway.handler.predicate; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; -import java.util.function.Predicate; +import java.util.Optional; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.cloud.gateway.support.SubnetUtils; -import org.springframework.http.server.reactive.ReactorServerHttpRequest; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.PublicDefaultServerRequest; +import org.springframework.web.reactive.function.server.RequestPredicate; /** * @author Spencer Gibb */ -public class RemoteAddrRoutePredicate implements RoutePredicate { +public class RemoteAddrRequestPredicateFactory implements RequestPredicateFactory { - private static final Log log = LogFactory.getLog(RemoteAddrRoutePredicate.class); + private static final Log log = LogFactory.getLog(RemoteAddrRequestPredicateFactory.class); @Override - public Predicate apply(String... args) { + public RequestPredicate apply(String... args) { validate(1, args); List sources = new ArrayList<>(); @@ -46,19 +46,21 @@ public class RemoteAddrRoutePredicate implements RoutePredicate { } } - return exchange -> { - ReactorServerHttpRequest request = (ReactorServerHttpRequest) exchange.getRequest(); - InetSocketAddress remoteAddress = request.getReactorRequest().remoteAddress(); - String hostAddress = remoteAddress.getAddress().getHostAddress(); - String host = exchange.getRequest().getURI().getHost(); + return req -> { + PublicDefaultServerRequest serverRequest = (PublicDefaultServerRequest) req; + Optional remoteAddress = serverRequest.getExchange().getRequest().getRemoteAddress(); + if (remoteAddress.isPresent()) { + String hostAddress = remoteAddress.get().getAddress().getHostAddress(); + String host = req.uri().getHost(); - if (!hostAddress.equals(host)) { - log.warn("Remote addresses didn't match " + hostAddress + " != " + host); - } + if (!hostAddress.equals(host)) { + log.warn("Remote addresses didn't match " + hostAddress + " != " + host); + } - for (SubnetUtils source : sources) { - if (source.getInfo().isInRange(hostAddress)) { - return true; + for (SubnetUtils source : sources) { + if (source.getInfo().isInRange(hostAddress)) { + return true; + } } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RequestPredicateFactory.java similarity index 82% rename from spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicate.java rename to spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RequestPredicateFactory.java index d6bebdc3..a3f72580 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RequestPredicateFactory.java @@ -17,17 +17,16 @@ package org.springframework.cloud.gateway.handler.predicate; -import java.util.function.Predicate; - import org.springframework.util.Assert; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.RequestPredicate; /** * @author Spencer Gibb */ -public interface RoutePredicate { +public interface RequestPredicateFactory { - Predicate apply(String... args); + //TODO: use tuple instead of String array + RequestPredicate apply(String... args); default void validate(int minimumSize, String... args) { Assert.isTrue(args != null && args.length >= minimumSize, diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NameUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NameUtils.java index 639cd80c..07f2e6bb 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NameUtils.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NameUtils.java @@ -18,15 +18,15 @@ package org.springframework.cloud.gateway.support; import org.springframework.cloud.gateway.filter.route.RouteFilter; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicate; +import org.springframework.cloud.gateway.handler.predicate.RequestPredicateFactory; /** * @author Spencer Gibb */ public class NameUtils { - public static String normalizePredicateName(Class clazz) { - return clazz.getSimpleName().replace(RoutePredicate.class.getSimpleName(), ""); + public static String normalizePredicateName(Class clazz) { + return clazz.getSimpleName().replace(RequestPredicateFactory.class.getSimpleName(), ""); } public static String normalizeFilterName(Class clazz) { diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/web/reactive/function/server/PublicDefaultServerRequest.java b/spring-cloud-gateway-core/src/main/java/org/springframework/web/reactive/function/server/PublicDefaultServerRequest.java new file mode 100644 index 00000000..5e3396fa --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/web/reactive/function/server/PublicDefaultServerRequest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.springframework.web.reactive.function.server; + +import org.springframework.http.HttpCookie; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; + +/** + * @author Spencer Gibb + */ +public class PublicDefaultServerRequest extends DefaultServerRequest { + private ServerWebExchange exchange; + + public PublicDefaultServerRequest(ServerWebExchange exchange) { + this(exchange, HandlerStrategies.withDefaults()); + } + + public PublicDefaultServerRequest(ServerWebExchange exchange, HandlerStrategies strategies) { + super(exchange, strategies); + this.exchange = exchange; + } + + public MultiValueMap getCookies() { + return this.exchange.getRequest().getCookies(); + } + + public ServerWebExchange getExchange() { + return exchange; + } +} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilterTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilterTests.java index 900dc18e..d6b5443e 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilterTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/route/SetPathRouteFilterTests.java @@ -22,9 +22,9 @@ import java.util.HashMap; import org.assertj.core.api.Assertions; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicate; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.MockServerHttpResponse; +import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; @@ -61,7 +61,7 @@ public class SetPathRouteFilterTests { .build(); DefaultServerWebExchange exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse()); - exchange.getAttributes().put(PathRoutePredicate.URL_PREDICATE_VARS_ATTR, variables); + exchange.getAttributes().put(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables); WebFilterChain filterChain = mock(WebFilterChain.class); diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRequestPredicateFactoryTests.java similarity index 82% rename from spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateTests.java rename to spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRequestPredicateFactoryTests.java index ce7a7bf2..0ab273b4 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRequestPredicateFactoryTests.java @@ -20,16 +20,16 @@ package org.springframework.cloud.gateway.handler.predicate; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.getExchange; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.minusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.minusHoursMillis; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.plusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.plusHoursMillis; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.getRequest; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.minusHours; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.minusHoursMillis; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.plusHours; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.plusHoursMillis; /** * @author Spencer Gibb */ -public class AfterRoutePredicateTests { +public class AfterRequestPredicateFactoryTests { @Test public void beforeStringWorks() { @@ -68,6 +68,6 @@ public class AfterRoutePredicateTests { } private boolean runPredicate(String dateString) { - return new AfterRoutePredicate().apply(dateString).test(getExchange()); + return new AfterRequestPredicateFactory().apply(dateString).test(getRequest()); } } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRequestPredicateFactoryTests.java similarity index 82% rename from spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateTests.java rename to spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRequestPredicateFactoryTests.java index 43e62cc2..992b0c89 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRequestPredicateFactoryTests.java @@ -20,16 +20,16 @@ package org.springframework.cloud.gateway.handler.predicate; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.getExchange; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.minusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.minusHoursMillis; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.plusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateTests.plusHoursMillis; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.getRequest; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.minusHours; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.minusHoursMillis; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.plusHours; +import static org.springframework.cloud.gateway.handler.predicate.BetweenRequestPredicateFactoryTests.plusHoursMillis; /** * @author Spencer Gibb */ -public class BeforeRoutePredicateTests { +public class BeforeRequestPredicateFactoryTests { @Test public void beforeStringWorks() { @@ -68,6 +68,6 @@ public class BeforeRoutePredicateTests { } private boolean runPredicate(String dateString) { - return new BeforeRoutePredicate().apply(dateString).test(getExchange()); + return new BeforeRequestPredicateFactory().apply(dateString).test(getRequest()); } } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRequestPredicateFactoryTests.java similarity index 88% rename from spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateTests.java rename to spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRequestPredicateFactoryTests.java index c4296ff8..0377fce4 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRequestPredicateFactoryTests.java @@ -23,7 +23,8 @@ import java.time.format.DateTimeFormatter; import org.junit.Test; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.MockServerHttpResponse; -import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.reactive.function.server.PublicDefaultServerRequest; +import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.server.adapter.DefaultServerWebExchange; import static org.assertj.core.api.Assertions.assertThat; @@ -31,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Spencer Gibb */ -public class BetweenRoutePredicateTests { +public class BetweenRequestPredicateFactoryTests { @Test public void beforeStringWorks() { @@ -94,7 +95,7 @@ public class BetweenRoutePredicateTests { } boolean runPredicate(String dateString1, String dateString2) { - return new BetweenRoutePredicate().apply(dateString1, dateString2).test(getExchange()); + return new BetweenRequestPredicateFactory().apply(dateString1, dateString2).test(getRequest()); } static String minusHoursMillis(int hours) { @@ -115,8 +116,8 @@ public class BetweenRoutePredicateTests { return ZonedDateTime.now().plusHours(hours).format(DateTimeFormatter.ISO_ZONED_DATE_TIME); } - static ServerWebExchange getExchange() { + static ServerRequest getRequest() { final MockServerHttpRequest request = MockServerHttpRequest.get("http://example.com").build(); - return new DefaultServerWebExchange(request, new MockServerHttpResponse()); + return new PublicDefaultServerRequest(new DefaultServerWebExchange(request, new MockServerHttpResponse())); } } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateIntegrationTests.java index f1f21074..2fe27ccf 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateIntegrationTests.java @@ -22,7 +22,7 @@ import org.junit.runner.RunWith; 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.handler.RequestPredicateHandlerMapping; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.context.annotation.Import; import org.springframework.http.HttpHeaders; @@ -56,7 +56,7 @@ public class HostRoutePredicateIntegrationTests extends BaseWebClientTests { assertStatus(response, HttpStatus.OK); HttpHeaders httpHeaders = response.headers().asHttpHeaders(); assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) - .isEqualTo(RoutePredicateHandlerMapping.class.getSimpleName()); + .isEqualTo(RequestPredicateHandlerMapping.class.getSimpleName()); assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) .isEqualTo("host_example_to_httpbin"); }) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/MethodRequestPredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/MethodRequestPredicateFactoryTests.java new file mode 100644 index 00000000..5c80d812 --- /dev/null +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/MethodRequestPredicateFactoryTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.springframework.cloud.gateway.handler.predicate; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.handler.RequestPredicateHandlerMapping; +import org.springframework.cloud.gateway.test.BaseWebClientTests; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.reactive.function.client.ClientResponse; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; +import static org.springframework.cloud.gateway.test.TestUtils.assertStatus; + +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT) +@DirtiesContext +public class MethodRequestPredicateFactoryTests extends BaseWebClientTests { + + @Test + public void hostRouteWorks() { + Mono result = webClient.get() + .uri("/get") + .header("Host", "www.method.org") + .exchange(); + + StepVerifier.create(result) + .consumeNextWith( + response -> { + assertStatus(response, HttpStatus.OK); + HttpHeaders httpHeaders = response.headers().asHttpHeaders(); + assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) + .isEqualTo(RequestPredicateHandlerMapping.class.getSimpleName()); + assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) + .isEqualTo("method_test"); + }) + .expectComplete() + .verify(DURATION); + } + + @EnableAutoConfiguration + @SpringBootConfiguration + @Import(DefaultTestConfig.class) + public static class TestConfig { } + +} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRequestPredicateFactoryTests.java similarity index 91% rename from spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateIntegrationTests.java rename to spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRequestPredicateFactoryTests.java index 4d39ee8a..327838cf 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRequestPredicateFactoryTests.java @@ -22,7 +22,7 @@ import org.junit.runner.RunWith; 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.handler.RequestPredicateHandlerMapping; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.context.annotation.Import; import org.springframework.http.HttpHeaders; @@ -41,7 +41,7 @@ import reactor.test.StepVerifier; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) @DirtiesContext -public class PathRoutePredicateIntegrationTests extends BaseWebClientTests { +public class PathRequestPredicateFactoryTests extends BaseWebClientTests { @Test public void pathRouteWorks() { @@ -55,7 +55,7 @@ public class PathRoutePredicateIntegrationTests extends BaseWebClientTests { assertStatus(response, HttpStatus.OK); HttpHeaders httpHeaders = response.headers().asHttpHeaders(); assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) - .isEqualTo(RoutePredicateHandlerMapping.class.getSimpleName()); + .isEqualTo(RequestPredicateHandlerMapping.class.getSimpleName()); assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) .isEqualTo("default_path_to_httpbin"); }) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java index 83a54e54..e50b94a5 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java @@ -29,7 +29,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; +import org.springframework.cloud.gateway.handler.RequestPredicateHandlerMapping; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; @@ -93,7 +93,7 @@ public class GatewayIntegrationTests extends BaseWebClientTests { assertStatus(response, HttpStatus.OK); HttpHeaders httpHeaders = response.headers().asHttpHeaders(); assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) - .isEqualTo(RoutePredicateHandlerMapping.class.getSimpleName()); + .isEqualTo(RequestPredicateHandlerMapping.class.getSimpleName()); assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) .isEqualTo("host_foo_path_headers_to_httpbin"); assertThat(httpHeaders.getFirst("X-Response-Foo")) diff --git a/spring-cloud-gateway-core/src/test/resources/application.yml b/spring-cloud-gateway-core/src/test/resources/application.yml index 362cdf58..6e46b5dc 100644 --- a/spring-cloud-gateway-core/src/test/resources/application.yml +++ b/spring-cloud-gateway-core/src/test/resources/application.yml @@ -80,6 +80,13 @@ spring: predicates: - Host=**.loadbalancerclient.org + # ===================================== + - id: method_test + uri: ${test.uri} + predicates: + - Method=GET + - Host=**.method.org + # ===================================== - id: redirect_to_test uri: ${test.uri}