From 3aff230f6a27b3032e7f9668d63d4c017572fc24 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 17 Mar 2017 23:47:30 -0600 Subject: [PATCH] Adds Routes, WebFilterFactories and GatewayRequestPredicates --- .../filter/factory/WebFilterFactories.java | 63 +++++++++++ .../predicate/GatewayRequestPredicates.java | 56 +++++++++ .../cloud/gateway/route/Route.java | 4 +- .../cloud/gateway/route/Routes.java | 107 ++++++++++++++++++ .../sample/GatewaySampleApplication.java | 29 ++--- .../sample/GatewaySampleApplicationTests.java | 1 - 6 files changed, 243 insertions(+), 17 deletions(-) create mode 100644 spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactories.java create mode 100644 spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayRequestPredicates.java create mode 100644 spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Routes.java diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactories.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactories.java new file mode 100644 index 00000000..dce80abe --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactories.java @@ -0,0 +1,63 @@ +/* + * 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.filter.factory; + +import org.springframework.tuple.Tuple; +import org.springframework.web.server.WebFilter; + +import static org.springframework.cloud.gateway.filter.factory.WebFilterFactory.NAME_KEY; +import static org.springframework.cloud.gateway.filter.factory.WebFilterFactory.VALUE_KEY; +import static org.springframework.tuple.TupleBuilder.tuple; + +/** + * @author Spencer Gibb + */ +public class WebFilterFactories { + //TODO: add support for AddRequestHeaderWebFilterFactory + + //TODO: add support for AddRequestParameterWebFilterFactory + + public static WebFilter addResponseHeader(String headerName, String headerValue) { + Tuple args = tuple().of(NAME_KEY, headerName, VALUE_KEY, headerValue); + return new AddResponseHeaderWebFilterFactory().apply(args); + } + + //TODO: add support for HystrixWebFilterFactory + + //TODO: add support for PrefixPathWebFilterFactory + + //TODO: add support for RedirectToWebFilterFactory + + //TODO: add support for RemoveNonProxyHeadersWebFilterFactory + + //TODO: add support for RemoveRequestHeaderWebFilterFactory + + //TODO: add support for RemoveResponseHeaderWebFilterFactory + + //TODO: add support for RewritePathWebFilterFactory + + //TODO: add support for SecureHeadersProperties + + //TODO: add support for SecureHeadersWebFilterFactory + + //TODO: add support for SetPathWebFilterFactory + + //TODO: add support for SetResponseHeaderWebFilterFactory + + //TODO: add support for SetStatusWebFilterFactory +} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayRequestPredicates.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayRequestPredicates.java new file mode 100644 index 00000000..f1a12538 --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayRequestPredicates.java @@ -0,0 +1,56 @@ +/* + * 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 static org.springframework.cloud.gateway.handler.predicate.PathRequestPredicateFactory.PATTERN_KEY; +import static org.springframework.tuple.TupleBuilder.tuple; + +/** + * @author Spencer Gibb + */ +public class GatewayRequestPredicates { + + //TODO: add support for AfterRequestPredicateFactory + + //TODO: add support for BeforeRequestPredicateFactory + + //TODO: add support for BetweenRequestPredicateFactory + + //TODO: add support for CookieRequestPredicateFactory + + //TODO: add support for GatewayRequestPredicates + + //TODO: add support for HeaderRequestPredicateFactory + + //TODO: add support for HostRequestPredicateFactory + + //TODO: add support for MethodRequestPredicateFactory + + public static RequestPredicate path(String pattern) { + return new PathRequestPredicateFactory().apply(tuple().of(PATTERN_KEY, pattern)); + } + + //TODO: add support for PredicateDefinition + + //TODO: add support for QueryRequestPredicateFactory + + //TODO: add support for RemoteAddrRequestPredicateFactory + +} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Route.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Route.java index e2dd2161..43b85978 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Route.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Route.java @@ -99,8 +99,8 @@ public class Route { return this; } - public Builder addAll(Collection webFilter) { - this.webFilters.addAll(webFilter); + public Builder addAll(Collection webFilters) { + this.webFilters.addAll(webFilters); return this; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Routes.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Routes.java new file mode 100644 index 00000000..b00fb5e3 --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Routes.java @@ -0,0 +1,107 @@ +/* + * 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.route; + +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.server.WebFilter; +import reactor.core.publisher.Flux; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Spencer Gibb + */ +public class Routes { + + public static LocatorBuilder locator() { + return new LocatorBuilder(); + } + + public static class LocatorBuilder { + + private List routes = new ArrayList<>(); + + public RouteBuilder route(String id) { + return new RouteBuilder(this).id(id); + } + + private void add(Route route) { + this.routes.add(route); + } + + public RouteLocator build() { + return () -> Flux.fromIterable(this.routes); + } + + } + + public static class RouteBuilder { + private final Route.Builder builder = Route.builder(); + private final LocatorBuilder locatorBuilder; + + private RouteBuilder(LocatorBuilder locatorBuilder) { + this.locatorBuilder = locatorBuilder; + } + + public RouteBuilder id(String id) { + this.builder.id(id); + return this; + } + + public RouteBuilder uri(String uri) { + this.builder.uri(uri); + return this; + } + + public RouteBuilder uri(URI uri) { + this.builder.uri(uri); + return this; + } + + public RouteBuilder predicate(RequestPredicate predicate) { + this.builder.requestPredicate(predicate); + return this; + } + + //TODO: maybe add WebFilterBuilder so no need to import WebFilterFactories? + public RouteBuilder webFilters(List webFilters) { + this.builder.webFilters(webFilters); + return this; + } + + public RouteBuilder add(WebFilter webFilter) { + this.builder.add(webFilter); + return this; + } + + public RouteBuilder addAll(Collection webFilters) { + this.builder.addAll(webFilters); + return this; + } + + public LocatorBuilder and() { + Route route = this.builder.build(); + this.locatorBuilder.add(route); + return this.locatorBuilder; + } + } + +} diff --git a/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java b/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java index 5b689b6c..7c727fa1 100644 --- a/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java +++ b/spring-cloud-gateway-sample/src/main/java/org/springframework/cloud/gateway/sample/GatewaySampleApplication.java @@ -21,14 +21,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.cloud.gateway.EnableGateway; -import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderWebFilterFactory; -import org.springframework.cloud.gateway.route.Route; import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.Routes; import org.springframework.context.annotation.Bean; -import org.springframework.tuple.TupleBuilder; -import org.springframework.web.reactive.function.server.RequestPredicates; -import reactor.core.publisher.Flux; +import static org.springframework.cloud.gateway.filter.factory.WebFilterFactories.addResponseHeader; +import static org.springframework.cloud.gateway.handler.predicate.GatewayRequestPredicates.path; +// import static org.springframework.web.reactive.function.server.RequestPredicates.path; /** * @author Spencer Gibb @@ -40,16 +39,18 @@ public class GatewaySampleApplication { @Bean public RouteLocator customRouteLocator() { - return () -> { - Route route = Route.builder() - .id("test") + return Routes.locator() + .route("test") .uri("http://httpbin.org:80") - .requestPredicate(RequestPredicates.path("/image/png")) - .add(new AddResponseHeaderWebFilterFactory() - .apply(TupleBuilder.tuple().of("name", "X-TestHeader", "value", "foobar"))) - .build(); - return Flux.just(route); - }; + .predicate(path("/image/png")) + .add(addResponseHeader("X-TestHeader", "foobar")) + .and() + .route("test2") + .uri("http://httpbin.org:80") + .predicate(path("/image/webp")) + .add(addResponseHeader("X-AnotherHeader", "baz")) + .and() + .build(); } public static void main(String[] args) { diff --git a/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java b/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java index 08003343..c077fd0b 100644 --- a/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java +++ b/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java @@ -50,7 +50,6 @@ public class GatewaySampleApplicationTests { @Before public void setup() { - //TODO: how to set new ReactorClientHttpConnector() baseUri = "http://localhost:" + port; this.webClient = WebClient.create(baseUri); }