diff --git a/pom.xml b/pom.xml index 816ba3a4..b2b4c7be 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ org.springframework.cloud spring-cloud-build - 2.0.0.BUILD-SNAPSHOT + 1.3.2.RELEASE @@ -48,9 +48,6 @@ UTF-8 UTF-8 1.8 - 2.0.0.BUILD-SNAPSHOT - 2.0.0.BUILD-SNAPSHOT - 1.0.0.RELEASE @@ -62,87 +59,12 @@ pom import - - org.springframework.cloud - spring-cloud-commons-dependencies - ${spring-cloud-commons.version} - pom - import - - - org.springframework.cloud - spring-cloud-netflix-dependencies - ${spring-cloud-netflix.version} - pom - import - - - org.springframework.cloud - spring-cloud-starter-ribbon - ${spring-cloud-netflix.version} - - - com.netflix.ribbon - ribbon-transport - - - io.reactivex - rxnetty - - - - - org.springframework.cloud - spring-cloud-starter-eureka - ${spring-cloud-netflix.version} - - - - org.springframework.boot - spring-boot-starter-web - - - - - org.springframework.cloud - spring-cloud-starter-hystrix - ${spring-cloud-netflix.version} - - - - io.reactivex - rxjava-reactive-streams - 1.2.1 - true - - - org.springframework.boot - spring-boot-devtools - ${spring-boot.version} - - - org.springframework - spring-tuple - ${spring-tuple.version} - - - org.springframework - spring-core - - - org.springframework - spring-context - - - spring-cloud-gateway-dependencies spring-cloud-gateway-mvc - spring-cloud-gateway-core - spring-cloud-starter-gateway spring-cloud-gateway-sample docs diff --git a/spring-cloud-gateway-core/pom.xml b/spring-cloud-gateway-core/pom.xml deleted file mode 100644 index 210c128f..00000000 --- a/spring-cloud-gateway-core/pom.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - 4.0.0 - - - org.springframework.cloud - spring-cloud-gateway - 1.0.0.BUILD-SNAPSHOT - .. - - spring-cloud-gateway-core - jar - Spring Cloud Gateway Core - Spring Cloud Gateway Core - - ${basedir}/.. - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-actuator - true - - - org.springframework.boot - spring-boot-starter-webflux - true - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.cloud - spring-cloud-starter-ribbon - true - - - org.springframework.cloud - spring-cloud-starter-hystrix - true - - - - io.reactivex - rxjava-reactive-streams - true - - - org.springframework.boot - spring-boot-devtools - true - - - org.springframework - spring-tuple - - - org.springframework.boot - spring-boot-starter-data-redis - true - - - org.springframework.cloud - spring-cloud-starter-eureka - test - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - org.assertj - assertj-core - test - - - org.synchronoss.cloud - nio-multipart-parser - 1.0.2 - test - - - javax.mail - javax.mail-api - 1.6.0-rc1 - test - - - com.sun.mail - javax.mail - 1.6.0-rc1 - test - - - - - java8plus - - [1.8,2.0) - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.0 - - - -parameters - - - - - - - - diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/EnableGateway.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/EnableGateway.java deleted file mode 100644 index 6ad6a87d..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/EnableGateway.java +++ /dev/null @@ -1,42 +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; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.cloud.gateway.config.GatewayConfiguration; -import org.springframework.context.annotation.Import; - -/** - * Annotation to activate Spring Cloud Gateway configuration {@link org.springframework.cloud.gateway.config.GatewayAutoConfiguration} - * - * @author Spencer Gibb - * - */ - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Import(GatewayConfiguration.class) -public @interface EnableGateway { - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java deleted file mode 100644 index eca32166..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java +++ /dev/null @@ -1,163 +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.actuate; - -import java.net.URI; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.route.RouteDefinitionLocator; -import org.springframework.cloud.gateway.route.RouteDefinitionWriter; -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.cloud.gateway.filter.factory.WebFilterFactory; -import org.springframework.cloud.gateway.route.Route; -import org.springframework.cloud.gateway.route.RouteDefinition; -import org.springframework.cloud.gateway.support.NotFoundException; -import org.springframework.cloud.gateway.route.RefreshRoutesEvent; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ApplicationEventPublisherAware; -import org.springframework.core.Ordered; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -//TODO: move to new Spring Boot 2.0 actuator when ready -//@ConfigurationProperties(prefix = "endpoints.gateway") -@RestController -@RequestMapping("/admin/gateway") -public class GatewayEndpoint implements ApplicationEventPublisherAware {/*extends AbstractEndpoint> {*/ - - private static final Log log = LogFactory.getLog(GatewayEndpoint.class); - - private RouteDefinitionLocator routeDefinitionLocator; - private List globalFilters; - private List webFilterFactories; - private RouteDefinitionWriter routeDefinitionWriter; - private RouteLocator routeLocator; - private ApplicationEventPublisher publisher; - - public GatewayEndpoint(RouteDefinitionLocator routeDefinitionLocator, List globalFilters, - List webFilterFactories, RouteDefinitionWriter routeDefinitionWriter, - RouteLocator routeLocator) { - //super("gateway"); - this.routeDefinitionLocator = routeDefinitionLocator; - this.globalFilters = globalFilters; - this.webFilterFactories = webFilterFactories; - this.routeDefinitionWriter = routeDefinitionWriter; - this.routeLocator = routeLocator; - } - - @Override - public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { - this.publisher = publisher; - } - - /*@Override - public Map invoke() { - }*/ - - // TODO: Add uncommited or new but not active routes endpoint - - //TODO: this should really be a listener that responds to a RefreshEvent - @PostMapping("/refresh") - public Mono refresh() { - this.publisher.publishEvent(new RefreshRoutesEvent(this)); - return Mono.empty(); - } - - @GetMapping("/globalfilters") - public Map globalfilters() { - return getNamesToOrders(this.globalFilters); - } - - @GetMapping("/routefilters") - public Map routefilers() { - return getNamesToOrders(this.webFilterFactories); - } - - private Map getNamesToOrders(List list) { - HashMap filters = new HashMap<>(); - - for (Object o : list) { - Integer order = null; - if (o instanceof Ordered) { - order = ((Ordered)o).getOrder(); - } - //filters.put(o.getClass().getName(), order); - filters.put(o.toString(), order); - } - - return filters; - } - - @GetMapping("/routes") - public Mono> routes() { - return this.routeDefinitionLocator.getRouteDefinitions().collectList(); - } - -/* -http POST :8080/admin/gateway/routes/apiaddreqhead uri=http://httpbin.org:80 predicates:='["Host=**.apiaddrequestheader.org", "Path=/headers"]' filters:='["AddRequestHeader=X-Request-ApiFoo, ApiBar"]' -*/ - @PostMapping("/routes/{id}") - @SuppressWarnings("unchecked") - public Mono> save(@PathVariable String id, @RequestBody Mono route) { - return this.routeDefinitionWriter.save(route.map(r -> { - r.setId(id); - log.debug("Saving route: " + route); - return r; - })).then(Mono.defer(() -> - Mono.just(ResponseEntity.created(URI.create("/routes/"+id)).build()) - )); - } - - @DeleteMapping("/routes/{id}") - public Mono> delete(@PathVariable String id) { - return this.routeDefinitionWriter.delete(Mono.just(id)) - .then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build()))) - .onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build())); - } - - @GetMapping("/routes/{id}") - public Mono> route(@PathVariable String id) { - return this.routeDefinitionLocator.getRouteDefinitions() - .filter(route -> route.getId().equals(id)) - .singleOrEmpty() - .map(route -> ResponseEntity.ok(route)) - .switchIfEmpty(Mono.just(ResponseEntity.notFound().build())); - } - - @GetMapping("/routes/{id}/combinedfilters") - public Map combinedfilters(@PathVariable String id) { - List routes = this.routeLocator.getRoutes().collectList().block(); - return getNamesToOrders(routes); - } -} 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 deleted file mode 100644 index 5eb3e318..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ /dev/null @@ -1,368 +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.config; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.actuate.endpoint.Endpoint; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.gateway.actuate.GatewayEndpoint; -import org.springframework.cloud.gateway.filter.GlobalFilter; -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.factory.AddRequestHeaderWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.AddRequestParameterWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.HystrixWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.PrefixPathWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.RedirectToWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.RemoveNonProxyHeadersWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.SecureHeadersProperties; -import org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.SetPathWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.SetStatusWebFilterFactory; -import org.springframework.cloud.gateway.filter.factory.WebFilterFactory; -import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; -import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter; -import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter; -import org.springframework.cloud.gateway.handler.FilteringWebHandler; -import org.springframework.cloud.gateway.handler.NettyProxyWebHandler; -import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; -import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; -import org.springframework.cloud.gateway.route.CachingRouteLocator; -import org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator; -import org.springframework.cloud.gateway.route.CompositeRouteLocator; -import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository; -import org.springframework.cloud.gateway.route.RouteDefinitionLocator; -import org.springframework.cloud.gateway.route.RouteDefinitionRepository; -import org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator; -import org.springframework.cloud.gateway.route.RouteDefinitionWriter; -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -import com.netflix.hystrix.HystrixObservableCommand; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.core.script.DefaultRedisScript; -import org.springframework.data.redis.core.script.RedisScript; -import org.springframework.scripting.support.ResourceScriptSource; -import reactor.core.publisher.Flux; -import reactor.ipc.netty.http.client.HttpClient; -import reactor.ipc.netty.resources.PoolResources; -import rx.RxReactiveStreams; - -/** - * @author Spencer Gibb - */ -@Configuration -@ConditionalOnBean(GatewayConfiguration.Marker.class) -@EnableConfigurationProperties -@AutoConfigureBefore(HttpHandlerAutoConfiguration.class) -@AutoConfigureAfter(GatewayLoadBalancerClientAutoConfiguration.class) -public class GatewayAutoConfiguration { - - @Configuration - @ConditionalOnClass(HttpClient.class) - protected static class NettyConfiguration { - @Bean - @ConditionalOnMissingBean - public HttpClient httpClient() { - return HttpClient.create(opts -> { - opts.poolResources(PoolResources.elastic("proxy")); - // opts.disablePool(); //TODO: why do I need this again? - }); - } - - @Bean - public NettyProxyWebHandler proxyWebHandler(HttpClient httpClient) { - return new NettyProxyWebHandler(httpClient); - } - - @Bean - public NettyRoutingFilter routingFilter(HttpClient httpClient) { - return new NettyRoutingFilter(httpClient); - } - } - - @Bean - public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) { - return new PropertiesRouteDefinitionLocator(properties); - } - - @Bean - @ConditionalOnMissingBean(RouteDefinitionRepository.class) - public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() { - return new InMemoryRouteDefinitionRepository(); - } - - @Bean - @Primary - public RouteDefinitionLocator routeDefinitionLocator(List routeDefinitionLocators) { - return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators)); - } - - @Bean - public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, - List webFilterFactories, - List predicates, - RouteDefinitionLocator routeDefinitionLocator) { - return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, webFilterFactories, properties); - } - - @Bean - @Primary - public RouteLocator routeLocator(List routeLocators) { - return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators))); - } - - @Bean - public FilteringWebHandler filteringWebHandler(List globalFilters) { - return new FilteringWebHandler(globalFilters); - } - - @Bean - public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, - RouteLocator routeLocator) { - return new RoutePredicateHandlerMapping(webHandler, routeLocator); - } - - // ConfigurationProperty beans - - @Bean - public GatewayProperties gatewayProperties() { - return new GatewayProperties(); - } - - @Bean - public SecureHeadersProperties secureHeadersProperties() { - return new SecureHeadersProperties(); - } - - // GlobalFilter beans - - @Bean - public RouteToRequestUrlFilter routeToRequestUrlFilter() { - return new RouteToRequestUrlFilter(); - } - - @Bean - public WriteResponseFilter writeResponseFilter() { - return new WriteResponseFilter(); - } - - // Predicate Factory beans - - @Bean - public AfterRoutePredicateFactory afterRoutePredicateFactory() { - return new AfterRoutePredicateFactory(); - } - - @Bean - public BeforeRoutePredicateFactory beforeRoutePredicateFactory() { - return new BeforeRoutePredicateFactory(); - } - - @Bean - public BetweenRoutePredicateFactory betweenRoutePredicateFactory() { - return new BetweenRoutePredicateFactory(); - } - - @Bean - public CookieRoutePredicateFactory cookieRoutePredicateFactory() { - return new CookieRoutePredicateFactory(); - } - - @Bean - public HeaderRoutePredicateFactory headerRoutePredicateFactory() { - return new HeaderRoutePredicateFactory(); - } - - @Bean - public HostRoutePredicateFactory hostRoutePredicateFactory() { - return new HostRoutePredicateFactory(); - } - - @Bean - public MethodRoutePredicateFactory methodRoutePredicateFactory() { - return new MethodRoutePredicateFactory(); - } - - @Bean - public PathRoutePredicateFactory pathRoutePredicateFactory() { - return new PathRoutePredicateFactory(); - } - - @Bean - public QueryRoutePredicateFactory queryRoutePredicateFactory() { - return new QueryRoutePredicateFactory(); - } - - @Bean - public RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory() { - return new RemoteAddrRoutePredicateFactory(); - } - - // WebFilter Factory beans - - @Bean - public AddRequestHeaderWebFilterFactory addRequestHeaderWebFilterFactory() { - return new AddRequestHeaderWebFilterFactory(); - } - - @Bean - public AddRequestParameterWebFilterFactory addRequestParameterWebFilterFactory() { - return new AddRequestParameterWebFilterFactory(); - } - - @Bean - public AddResponseHeaderWebFilterFactory addResponseHeaderWebFilterFactory() { - return new AddResponseHeaderWebFilterFactory(); - } - - @Configuration - @ConditionalOnClass({HystrixObservableCommand.class, RxReactiveStreams.class}) - protected static class HystrixConfiguration { - @Bean - public HystrixWebFilterFactory hystrixWebFilterFactory() { - return new HystrixWebFilterFactory(); - } - } - - @Bean - public PrefixPathWebFilterFactory prefixPathWebFilterFactory() { - return new PrefixPathWebFilterFactory(); - } - - @Bean - public RedirectToWebFilterFactory redirectToWebFilterFactory() { - return new RedirectToWebFilterFactory(); - } - - @Bean - public RemoveNonProxyHeadersWebFilterFactory removeNonProxyHeadersWebFilterFactory() { - return new RemoveNonProxyHeadersWebFilterFactory(); - } - - @Bean - public RemoveRequestHeaderWebFilterFactory removeRequestHeaderWebFilterFactory() { - return new RemoveRequestHeaderWebFilterFactory(); - } - - @Bean - public RemoveResponseHeaderWebFilterFactory removeResponseHeaderWebFilterFactory() { - return new RemoveResponseHeaderWebFilterFactory(); - } - - @Bean - @ConditionalOnBean({RateLimiter.class, KeyResolver.class}) - public RequestRateLimiterWebFilterFactory requestRateLimiterWebFilterFactory(RateLimiter rateLimiter) { - return new RequestRateLimiterWebFilterFactory(rateLimiter); - } - - @Bean - public RewritePathWebFilterFactory rewritePathWebFilterFactory() { - return new RewritePathWebFilterFactory(); - } - - @Bean - public SetPathWebFilterFactory setPathWebFilterFactory() { - return new SetPathWebFilterFactory(); - } - - @Bean - public SecureHeadersWebFilterFactory secureHeadersWebFilterFactory(SecureHeadersProperties properties) { - return new SecureHeadersWebFilterFactory(properties); - } - - @Bean - public SetResponseHeaderWebFilterFactory setResponseHeaderWebFilterFactory() { - return new SetResponseHeaderWebFilterFactory(); - } - - @Bean - public SetStatusWebFilterFactory setStatusWebFilterFactory() { - return new SetStatusWebFilterFactory(); - } - - - @ConditionalOnClass(RedisTemplate.class) - protected static class GatewayRedisConfiguration { - @Bean - public RedisScript redistRequestRateLimiterScript() { - DefaultRedisScript redisScript = new DefaultRedisScript<>(); - redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("META-INF/scripts/request_rate_limiter.lua"))); - redisScript.setResultType(List.class); - return redisScript; - } - - @Bean - public RedisRateLimiter redisRateLimiter(StringRedisTemplate redisTemplate, - @Qualifier("redistRequestRateLimiterScript") RedisScript redisScript) { - return new RedisRateLimiter(redisTemplate, redisScript); - } - } - - /*@Bean - public RouterFunction test() { - RouterFunction route = RouterFunctions.route( - RequestPredicates.path("/testfun"), - request -> ServerResponse.ok().body(BodyInserters.fromObject("hello"))); - return route; - }*/ - - @Configuration - @ConditionalOnClass(Endpoint.class) - protected static class GatewayActuatorConfiguration { - - @Bean - public GatewayEndpoint gatewayEndpoint(RouteDefinitionLocator routeDefinitionLocator, List globalFilters, - List webFilterFactories, RouteDefinitionWriter routeDefinitionWriter, - RouteLocator routeLocator) { - return new GatewayEndpoint(routeDefinitionLocator, globalFilters, webFilterFactories, routeDefinitionWriter, routeLocator); - } - } - -} - diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayConfiguration.java deleted file mode 100644 index 97d03ecd..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayConfiguration.java +++ /dev/null @@ -1,35 +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.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Spencer Gibb - */ -@Configuration -public class GatewayConfiguration { - - @Bean - public Marker gatewayMarker() { - return new Marker(); - } - - class Marker { } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayLoadBalancerClientAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayLoadBalancerClientAutoConfiguration.java deleted file mode 100644 index c7043424..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayLoadBalancerClientAutoConfiguration.java +++ /dev/null @@ -1,45 +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.config; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; -import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Spencer Gibb - */ -@Configuration -@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class}) -@ConditionalOnBean(GatewayConfiguration.Marker.class) -@AutoConfigureAfter(RibbonAutoConfiguration.class) -public class GatewayLoadBalancerClientAutoConfiguration { - - // GlobalFilter beans - - @Bean - @ConditionalOnBean(LoadBalancerClient.class) - public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) { - return new LoadBalancerClientFilter(client); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java deleted file mode 100644 index 0fbd5e6c..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java +++ /dev/null @@ -1,76 +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.config; - -import java.util.ArrayList; -import java.util.List; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.gateway.filter.FilterDefinition; -import org.springframework.cloud.gateway.route.RouteDefinition; -import org.springframework.cloud.gateway.filter.factory.RemoveNonProxyHeadersWebFilterFactory; -import org.springframework.validation.annotation.Validated; - -import static org.springframework.cloud.gateway.support.NameUtils.normalizeFilterName; - -/** - * @author Spencer Gibb - */ -@ConfigurationProperties("spring.cloud.gateway") -@Validated -public class GatewayProperties { - - /** - * List of Routes - */ - @NotNull - @Valid - private List routes = new ArrayList<>(); - - /** - * List of filter definitions that are applied to every route. - */ - private List defaultFilters = loadDefaults(); - - private ArrayList loadDefaults() { - ArrayList defaults = new ArrayList<>(); - FilterDefinition definition = new FilterDefinition(); - definition.setName(normalizeFilterName(RemoveNonProxyHeadersWebFilterFactory.class)); - defaults.add(definition); - return defaults; - } - - public List getRoutes() { - return routes; - } - - public void setRoutes(List routes) { - this.routes = routes; - } - - public List getDefaultFilters() { - return defaultFilters; - } - - public void setDefaultFilters(List defaultFilters) { - this.defaultFilters = defaultFilters; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/PropertiesRouteDefinitionLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/PropertiesRouteDefinitionLocator.java deleted file mode 100644 index b5266539..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/PropertiesRouteDefinitionLocator.java +++ /dev/null @@ -1,40 +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.config; - -import org.springframework.cloud.gateway.route.RouteDefinition; -import org.springframework.cloud.gateway.route.RouteDefinitionLocator; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator { - - private final GatewayProperties properties; - - public PropertiesRouteDefinitionLocator(GatewayProperties properties) { - this.properties = properties; - } - - @Override - public Flux getRouteDefinitions() { - return Flux.fromIterable(this.properties.getRoutes()); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator.java deleted file mode 100644 index 9e1bae96..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator.java +++ /dev/null @@ -1,82 +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.discovery; - -import java.net.URI; - -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.gateway.route.RouteDefinitionLocator; -import org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory; -import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory; -import org.springframework.cloud.gateway.filter.FilterDefinition; -import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; -import org.springframework.cloud.gateway.route.RouteDefinition; - -import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REGEXP_KEY; -import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REPLACEMENT_KEY; -import static org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory.PATTERN_KEY; -import static org.springframework.cloud.gateway.support.NameUtils.normalizeFilterName; -import static org.springframework.cloud.gateway.support.NameUtils.normalizePredicateName; - -import reactor.core.publisher.Flux; - -/** - * TODO: developer configuration, in zuul, this was opt out, should be opt in - * @author Spencer Gibb - */ -public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLocator { - - private final DiscoveryClient discoveryClient; - private final String routeIdPrefix; - - public DiscoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient) { - this.discoveryClient = discoveryClient; - this.routeIdPrefix = this.discoveryClient.getClass().getSimpleName() + "_"; - } - - @Override - public Flux getRouteDefinitions() { - return Flux.fromIterable(discoveryClient.getServices()) - .map(serviceId -> { - RouteDefinition routeDefinition = new RouteDefinition(); - routeDefinition.setId(this.routeIdPrefix + serviceId); - routeDefinition.setUri(URI.create("lb://" + serviceId)); - - // add a predicate that matches the url at /serviceId* - PredicateDefinition predicate = new PredicateDefinition(); - predicate.setName(normalizePredicateName(PathRoutePredicateFactory.class)); - predicate.addArg(PATTERN_KEY, "/" + serviceId + "*"); - routeDefinition.getPredicates().add(predicate); - - //TODO: support for other default predicates - - // add a filter that removes /serviceId by default - FilterDefinition filter = new FilterDefinition(); - filter.setName(normalizeFilterName(RewritePathWebFilterFactory.class)); - String regex = "/" + serviceId + "/(?.*)"; - String replacement = "/${remaining}"; - filter.addArg(REGEXP_KEY, regex); - filter.addArg(REPLACEMENT_KEY, replacement); - routeDefinition.getFilters().add(filter); - - //TODO: support for default filters - - return routeDefinition; - }); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/FilterDefinition.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/FilterDefinition.java deleted file mode 100644 index 5923e871..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/FilterDefinition.java +++ /dev/null @@ -1,100 +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.filter; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Objects; - -import javax.validation.constraints.NotNull; - -import org.springframework.cloud.gateway.support.NameUtils; -import org.springframework.validation.annotation.Validated; - -import static org.springframework.util.StringUtils.tokenizeToStringArray; - -/** - * @author Spencer Gibb - */ -@Validated -public class FilterDefinition { - @NotNull - private String name; - private Map args = new LinkedHashMap<>(); - - public FilterDefinition() { - } - - public FilterDefinition(String text) { - int eqIdx = text.indexOf("="); - if (eqIdx <= 0) { - setName(text); - return; - } - setName(text.substring(0, eqIdx)); - - String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ","); - - for (int i=0; i < args.length; i++) { - this.args.put(NameUtils.generateName(i), args[i]); - } - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map getArgs() { - return args; - } - - public void setArgs(Map args) { - this.args = args; - } - - public void addArg(String key, String value) { - this.args.put(key, value); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - FilterDefinition that = (FilterDefinition) o; - return Objects.equals(name, that.name) && - Objects.equals(args, that.args); - } - - @Override - public int hashCode() { - return Objects.hash(name, args); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("FilterDefinition{"); - sb.append("name='").append(name).append('\''); - sb.append(", args=").append(args); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/GlobalFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/GlobalFilter.java deleted file mode 100644 index e2ef71c8..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/GlobalFilter.java +++ /dev/null @@ -1,44 +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.filter; - -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilterChain; - -import reactor.core.publisher.Mono; - -/** - * Contract for interception-style, chained processing of Web requests that may - * be used to implement cross-cutting, application-agnostic requirements such - * as security, timeouts, and others. - * - * @author Rossen Stoyanchev - * @since 5.0 - */ -public interface GlobalFilter { - - /** - * Process the Web request and (optionally) delegate to the next - * {@code WebFilter} through the given {@link WebFilterChain}. - * @param exchange the current server exchange - * @param chain provides a way to delegate to the next filter - * @return {@code Mono} to indicate when request processing is complete - */ - Mono filter(ServerWebExchange exchange, WebFilterChain chain); - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilter.java deleted file mode 100644 index aa1b7084..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilter.java +++ /dev/null @@ -1,81 +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.filter; - -import java.net.URI; -import java.util.Optional; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.gateway.support.NotFoundException; -import org.springframework.core.Ordered; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilterChain; -import org.springframework.web.util.UriComponentsBuilder; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class LoadBalancerClientFilter implements GlobalFilter, Ordered { - - private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class); - public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100; - - private final LoadBalancerClient loadBalancer; - - public LoadBalancerClientFilter(LoadBalancerClient loadBalancer) { - this.loadBalancer = loadBalancer; - } - - @Override - public int getOrder() { - return LOAD_BALANCER_CLIENT_FILTER_ORDER; - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - Optional url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); - if (!url.isPresent() || !url.get().getScheme().equals("lb")) { - return chain.filter(exchange); - } - log.trace("LoadBalancerClientFilter url before: " + url.get()); - - final ServiceInstance instance = loadBalancer.choose(url.get().getHost()); - - if (instance == null) { - throw new NotFoundException(""); - } - - URI requestUrl = UriComponentsBuilder.fromUri(url.get()) - .scheme(instance.isSecure()? "https" : "http") //TODO: support websockets - .host(instance.getHost()) - .port(instance.getPort()) - .build(true) - .toUri(); - log.trace("LoadBalancerClientFilter url chosen: " + requestUrl); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl); - return chain.filter(exchange); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java deleted file mode 100644 index fe08475f..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java +++ /dev/null @@ -1,113 +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.filter; - -import java.net.URI; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.springframework.core.Ordered; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilterChain; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; - -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultHttpHeaders; -import io.netty.handler.codec.http.HttpMethod; -import reactor.core.publisher.Mono; -import reactor.ipc.netty.NettyPipeline; -import reactor.ipc.netty.http.client.HttpClient; -import reactor.ipc.netty.http.client.HttpClientRequest; - -/** - * @author Spencer Gibb - */ -public class NettyRoutingFilter implements GlobalFilter, Ordered { - - private final HttpClient httpClient; - - public NettyRoutingFilter(HttpClient httpClient) { - this.httpClient = httpClient; - } - - @Override - public int getOrder() { - return 2000000; - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - Optional requestUrl = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); - if (!requestUrl.isPresent()) { - return Mono.error(new IllegalStateException("No URI found in attribute: " + GATEWAY_REQUEST_URL_ATTR)); - } - - ServerHttpRequest request = exchange.getRequest(); - - final HttpMethod method = HttpMethod.valueOf(request.getMethod().toString()); - final String url = requestUrl.get().toString(); - - final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders(); - request.getHeaders().forEach(httpHeaders::set); - - return this.httpClient.request(method, url, req -> { - final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach) - .failOnClientError(false) - .headers(httpHeaders); - - if (MediaType.APPLICATION_FORM_URLENCODED.includes(request.getHeaders().getContentType())) { - return exchange.getFormData() - .flatMap(map -> proxyRequest.sendForm(form -> { - for (Map.Entry> entry: map.entrySet()) { - for (String value : entry.getValue()) { - form.attr(entry.getKey(), value); - } - } - }).then()) - .then(chain.filter(exchange)); - } - - return proxyRequest.sendHeaders() - .send(request.getBody() - .map(DataBuffer::asByteBuffer) - .map(Unpooled::wrappedBuffer)); - }).flatMap(res -> { - ServerHttpResponse response = exchange.getResponse(); - // put headers and status so filters can modify the response - HttpHeaders headers = new HttpHeaders(); - res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue())); - - response.getHeaders().putAll(headers); - response.setStatusCode(HttpStatus.valueOf(res.status().code())); - - // Defer committing the response until all route filters have run - // Put client response as ServerWebExchange attribute and write response later WriteResponseFilter - exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res); - return Mono.empty(); - }).then(chain.filter(exchange)); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedWebFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedWebFilter.java deleted file mode 100644 index caf29c98..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedWebFilter.java +++ /dev/null @@ -1,57 +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.filter; - -import org.springframework.core.Ordered; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class OrderedWebFilter implements WebFilter, Ordered { - - private final WebFilter delegate; - private final int order; - - public OrderedWebFilter(WebFilter delegate, int order) { - this.delegate = delegate; - this.order = order; - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - return this.delegate.filter(exchange, chain); - } - - @Override - public int getOrder() { - return this.order; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("OrderedWebFilter{"); - sb.append("delegate=").append(delegate); - sb.append(", order=").append(order); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/RouteToRequestUrlFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/RouteToRequestUrlFilter.java deleted file mode 100644 index 613b6d85..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/RouteToRequestUrlFilter.java +++ /dev/null @@ -1,64 +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.filter; - -import java.net.URI; -import java.util.Optional; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.route.Route; -import org.springframework.core.Ordered; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilterChain; -import org.springframework.web.util.UriComponentsBuilder; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class RouteToRequestUrlFilter implements GlobalFilter, Ordered { - - private static final Log log = LogFactory.getLog(RouteToRequestUrlFilter.class); - public static final int ROUTE_TO_URL_FILTER_ORDER = 10000; - - @Override - public int getOrder() { - return ROUTE_TO_URL_FILTER_ORDER; - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - Optional route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); - if (!route.isPresent()) { - return chain.filter(exchange); - } - log.info("RouteToRequestUrlFilter start"); - URI requestUrl = UriComponentsBuilder.fromHttpRequest(exchange.getRequest()) - .uri(route.get().getUri()) - .build(true) - .toUri(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl); - return chain.filter(exchange); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WriteResponseFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WriteResponseFilter.java deleted file mode 100644 index f8b373b7..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WriteResponseFilter.java +++ /dev/null @@ -1,75 +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.filter; - -import java.util.Optional; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.core.Ordered; -import org.springframework.core.io.buffer.NettyDataBuffer; -import org.springframework.core.io.buffer.NettyDataBufferFactory; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilterChain; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.ipc.netty.http.client.HttpClientResponse; - -/** - * @author Spencer Gibb - */ -public class WriteResponseFilter implements GlobalFilter, Ordered { - - private static final Log log = LogFactory.getLog(WriteResponseFilter.class); - - public static final int WRITE_RESPONSE_FILTER_ORDER = -1; - - @Override - public int getOrder() { - return WRITE_RESPONSE_FILTER_ORDER; - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - // NOTICE: nothing in "pre" filter stage as CLIENT_RESPONSE_ATTR is not added - // until the WebHandler is run - return chain.filter(exchange).then(Mono.defer(() -> { - Optional clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR); - // HttpClientResponse clientResponse = getAttribute(exchange, CLIENT_RESPONSE_ATTR, HttpClientResponse.class); - if (!clientResponse.isPresent()) { - return Mono.empty(); - } - log.trace("WriteResponseFilter start"); - ServerHttpResponse response = exchange.getResponse(); - - NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory(); - //TODO: what if it's not netty - - final Flux body = clientResponse.get().receive() - .retain() //TODO: needed? - .map(factory::wrap); - - return response.writeWith(body); - })); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactory.java deleted file mode 100644 index 36e835cb..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactory.java +++ /dev/null @@ -1,50 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; -import org.springframework.http.server.reactive.ServerHttpRequest; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class AddRequestHeaderWebFilterFactory implements WebFilterFactory { - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY, VALUE_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - String name = args.getString(NAME_KEY); - String value = args.getString(VALUE_KEY); - - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest().mutate() - .header(name, value) - .build(); - - return chain.filter(exchange.mutate().request(request).build()); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactory.java deleted file mode 100644 index 8ba913c2..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactory.java +++ /dev/null @@ -1,164 +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.filter.factory; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.List; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.server.reactive.RequestPath; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpRequestDecorator; -import org.springframework.tuple.Tuple; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; -import org.springframework.web.server.WebFilter; - -/** - * @author Spencer Gibb - */ -public class AddRequestParameterWebFilterFactory implements WebFilterFactory { - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY, VALUE_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - String parameter = args.getString(NAME_KEY); - String value = args.getString(VALUE_KEY); - - return (exchange, chain) -> { - - URI uri = exchange.getRequest().getURI(); - StringBuilder query = new StringBuilder(); - String originalQuery = uri.getQuery(); - - if (StringUtils.hasText(originalQuery)) { - query.append(originalQuery); - if (originalQuery.charAt(originalQuery.length() - 1) != '&') { - query.append('&'); - } - } - - //TODO urlencode? - query.append(parameter); - query.append('='); - query.append(value); - - ServerHttpRequest request = new QueryParamServerHttpRequestBuilder(exchange.getRequest()) - .query(query.toString()) - .build(); - - return chain.filter(exchange.mutate().request(request).build()); - }; - } - - class QueryParamServerHttpRequestBuilder implements ServerHttpRequest.Builder { - - private final ServerHttpRequest delegate; - private String query; - - public QueryParamServerHttpRequestBuilder(ServerHttpRequest delegate) { - Assert.notNull(delegate, "ServerHttpRequest delegate is required"); - this.delegate = delegate; - } - - - @Override - public ServerHttpRequest.Builder method(HttpMethod httpMethod) { - throw new UnsupportedOperationException(); - } - - @Override - public ServerHttpRequest.Builder path(String path) { - throw new UnsupportedOperationException(); - } - - public ServerHttpRequest.Builder query(String query) { - this.query = query; - return this; - } - - @Override - public ServerHttpRequest.Builder contextPath(String contextPath) { - throw new UnsupportedOperationException(); - } - - @Override - public ServerHttpRequest.Builder header(String key, String value) { - throw new UnsupportedOperationException(); - } - - @Override - public ServerHttpRequest build() { - URI uri = null; - if (this.query != null) { - uri = this.delegate.getURI(); - try { - uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), - uri.getPath(), this.query, uri.getFragment()); - } catch (URISyntaxException ex) { - throw new IllegalStateException("Invalid URI query: \"" + this.query + "\""); - } - } - return new MutativeDecorator(this.delegate, uri); - } - - - /** - * An immutable wrapper of a request returning property overrides -- given - * to the constructor -- or original values otherwise. - */ - private class MutativeDecorator extends ServerHttpRequestDecorator { - - private final URI uri; - - public MutativeDecorator(ServerHttpRequest delegate, URI uri) { - super(delegate); - - this.uri = uri; - } - - @Override - public HttpMethod getMethod() { - return super.getMethod(); - } - - @Override - public URI getURI() { - return (this.uri != null ? this.uri : super.getURI()); - } - - @Override - public RequestPath getPath() { - return super.getPath(); - } - - @Override - public HttpHeaders getHeaders() { - return super.getHeaders(); - } - } - - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderWebFilterFactory.java deleted file mode 100644 index 78e8c127..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderWebFilterFactory.java +++ /dev/null @@ -1,47 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class AddResponseHeaderWebFilterFactory implements WebFilterFactory { - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY, VALUE_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - final String header = args.getString(NAME_KEY); - final String value = args.getString(VALUE_KEY); - - return (exchange, chain) -> { - exchange.getResponse().getHeaders().add(header, value); - - return chain.filter(exchange); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactory.java deleted file mode 100644 index 75f42fd3..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactory.java +++ /dev/null @@ -1,84 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; - -import com.netflix.hystrix.HystrixCommandGroupKey; -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixObservableCommand; - -import reactor.core.publisher.Mono; -import rx.Observable; -import rx.RxReactiveStreams; -import rx.Subscription; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class HystrixWebFilterFactory implements WebFilterFactory { - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - //TODO: if no name is supplied, generate one from command id (useful for default filter) - final String commandName = args.getString(NAME_KEY); - final HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey(getClass().getSimpleName()); - final HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(commandName); - - final HystrixObservableCommand.Setter setter = HystrixObservableCommand.Setter - .withGroupKey(groupKey) - .andCommandKey(commandKey); - - return (exchange, chain) -> { - RouteHystrixCommand command = new RouteHystrixCommand(setter, exchange, chain); - - return Mono.create(s -> { - Subscription sub = command.toObservable().subscribe(s::success, s::error, s::success); - s.onCancel(sub::unsubscribe); - }); - }; - } - - //TODO: replace with HystrixMonoCommand that we write - private class RouteHystrixCommand extends HystrixObservableCommand { - private final ServerWebExchange exchange; - private final WebFilterChain chain; - - RouteHystrixCommand(Setter setter, ServerWebExchange exchange, WebFilterChain chain) { - super(setter); - this.exchange = exchange; - this.chain = chain; - } - - @Override - protected Observable construct() { - return RxReactiveStreams.toObservable(this.chain.filter(this.exchange)); - } - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathWebFilterFactory.java deleted file mode 100644 index 6cec28da..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathWebFilterFactory.java +++ /dev/null @@ -1,55 +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.filter.factory; - -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class PrefixPathWebFilterFactory implements WebFilterFactory { - - public static final String PREFIX_KEY = "prefix"; - - @Override - public List argNames() { - return Arrays.asList(PREFIX_KEY); - } - - @Override - @SuppressWarnings("unchecked") - public WebFilter apply(Tuple args) { - final String prefix = args.getString(PREFIX_KEY); - - return (exchange, chain) -> { - ServerHttpRequest req = exchange.getRequest(); - String newPath = prefix + req.getURI().getPath(); - - ServerHttpRequest request = req.mutate() - .path(newPath) - .build(); - - return chain.filter(exchange.mutate().request(request).build()); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactory.java deleted file mode 100644 index b394f235..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactory.java +++ /dev/null @@ -1,76 +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.filter.factory; - -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.util.Arrays; -import java.util.List; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.parse; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class RedirectToWebFilterFactory implements WebFilterFactory { - - public static final String STATUS_KEY = "status"; - public static final String URL_KEY = "url"; - - @Override - public List argNames() { - return Arrays.asList(STATUS_KEY, URL_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - String statusString = args.getRawString(STATUS_KEY); - String urlString = args.getString(URL_KEY); - - final HttpStatus httpStatus = parse(statusString); - final URL url; - try { - url = URI.create(urlString).toURL(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Invalid url " + urlString, e); - } - - return (exchange, chain) -> - chain.filter(exchange).then(Mono.defer(() -> { - if (!exchange.getResponse().isCommitted()) { - setResponseStatus(exchange, httpStatus); - - final ServerHttpResponse response = exchange.getResponse(); - response.getHeaders().set(HttpHeaders.LOCATION, url.toString()); - return response.setComplete(); - } - return Mono.empty(); - })); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactory.java deleted file mode 100644 index 2a990ef9..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactory.java +++ /dev/null @@ -1,82 +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.filter.factory; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import java.util.Arrays; -import java.util.List; - -/** - * Hop-by-hop header fields, which are meaningful only for a single transport-level connection, - * and are not stored by caches or forwarded by proxies. The following HTTP/1.1 header fields - * are hop-by-hop header fields: - *
    - *
  • Connection - *
  • Keep-Alive - *
  • Proxy-Authenticate - *
  • Proxy-Authorization - *
  • TE - *
  • Trailer - *
  • Transfer-Encoding - *
  • Upgrade - *
- * - * See https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-14#section-7.1.3 - * - * @author Spencer Gibb - */ -@ConfigurationProperties("spring.cloud.gateway.filter.remove-non-proxy-headers") -public class RemoveNonProxyHeadersWebFilterFactory implements WebFilterFactory { - - private static final String FAKE_HEADER = "_______force_______"; - public static final String[] DEFAULT_HEADERS_TO_REMOVE = new String[] {"Connection", "Keep-Alive", - "Proxy-Authenticate", "Proxy-Authorization", "TE", "Trailer", "Transfer-Encoding", "Upgrade"}; - - private List headers = Arrays.asList(DEFAULT_HEADERS_TO_REMOVE); - - public List getHeaders() { - return headers; - } - - public void setHeaders(List headers) { - this.headers = headers; - } - - @Override - public WebFilter apply(Tuple args) { - //TODO: support filter args - - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest().mutate() - .header(FAKE_HEADER, "mutable") //TODO: is there a better way? - .build(); - - request.getHeaders().remove(FAKE_HEADER); - - for (String header : this.headers) { - request.getHeaders().remove(header); - } - - return chain.filter(exchange.mutate().request(request).build()); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactory.java deleted file mode 100644 index 580fd834..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactory.java +++ /dev/null @@ -1,54 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; -import org.springframework.http.server.reactive.ServerHttpRequest; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class RemoveRequestHeaderWebFilterFactory implements WebFilterFactory { - - private static final String FAKE_HEADER = "_______force_______"; - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - final String header = args.getString(NAME_KEY); - - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest().mutate() - .header(FAKE_HEADER, "mutable") //TODO: is there a better way? - .build(); - - request.getHeaders().remove(FAKE_HEADER); - request.getHeaders().remove(header); - - return chain.filter(exchange.mutate().request(request).build()); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactory.java deleted file mode 100644 index 6f751431..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactory.java +++ /dev/null @@ -1,46 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class RemoveResponseHeaderWebFilterFactory implements WebFilterFactory { - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - final String header = args.getString(NAME_KEY); - - return (exchange, chain) -> { - exchange.getResponse().getHeaders().remove(header); - - return chain.filter(exchange); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestRateLimiterWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestRateLimiterWebFilterFactory.java deleted file mode 100644 index 9f54f089..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestRateLimiterWebFilterFactory.java +++ /dev/null @@ -1,87 +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.filter.factory; - -import org.springframework.beans.BeansException; -import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; -import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter; -import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter.Response; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.http.HttpStatus; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import java.util.Arrays; -import java.util.List; - -/** - * User Request Rate Limiter filter. - * See https://stripe.com/blog/rate-limiters and - */ -public class RequestRateLimiterWebFilterFactory implements WebFilterFactory, ApplicationContextAware { - - public static final String REPLENISH_RATE_KEY = "replenishRate"; - public static final String BURST_CAPACITY_KEY = "burstCapacity"; - public static final String KEY_RESOLVER_NAME_KEY = "keyResolverName"; - - private final RateLimiter rateLimiter; - private ApplicationContext context; - - public RequestRateLimiterWebFilterFactory(RateLimiter rateLimiter) { - this.rateLimiter = rateLimiter; - } - - @Override - public void setApplicationContext(ApplicationContext context) throws BeansException { - this.context = context; - } - - - @Override - public List argNames() { - return Arrays.asList(REPLENISH_RATE_KEY, BURST_CAPACITY_KEY, KEY_RESOLVER_NAME_KEY); - } - - @SuppressWarnings("unchecked") - @Override - public WebFilter apply(Tuple args) { - // How many requests per second do you want a user to be allowed to do? - int replenishRate = args.getInt(REPLENISH_RATE_KEY); - - // How much bursting do you want to allow? - int capacity = args.getInt(BURST_CAPACITY_KEY); - - String beanName = args.getString(KEY_RESOLVER_NAME_KEY); - KeyResolver keyResolver = this.context.getBean(beanName, KeyResolver.class); - - return (exchange, chain) -> - keyResolver.resolve(exchange).flatMap(key -> { - Response response = rateLimiter.isAllowed(key, replenishRate, capacity); - - //TODO: set some headers for rate, tokens left - - if (response.isAllowed()) { - return chain.filter(exchange); - } - exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); - return exchange.getResponse().setComplete(); - }); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactory.java deleted file mode 100644 index d5d4dd38..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactory.java +++ /dev/null @@ -1,57 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; -import org.springframework.http.server.reactive.ServerHttpRequest; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class RewritePathWebFilterFactory implements WebFilterFactory { - - public static final String REGEXP_KEY = "regexp"; - public static final String REPLACEMENT_KEY = "replacement"; - - @Override - public List argNames() { - return Arrays.asList(REGEXP_KEY, REPLACEMENT_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - final String regex = args.getString(REGEXP_KEY); - String replacement = args.getString(REPLACEMENT_KEY).replace("$\\", "$"); - - return (exchange, chain) -> { - ServerHttpRequest req = exchange.getRequest(); - String path = req.getURI().getPath(); - String newPath = path.replaceAll(regex, replacement); - - ServerHttpRequest request = req.mutate() - .path(newPath) - .build(); - - return chain.filter(exchange.mutate().request(request).build()); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersProperties.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersProperties.java deleted file mode 100644 index bf5226f8..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersProperties.java +++ /dev/null @@ -1,123 +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.filter.factory; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * @author Spencer Gibb - */ -@ConfigurationProperties("spring.cloud.gateway.filter.secure-headers") -public class SecureHeadersProperties { - public static final String X_XSS_PROTECTION_HEADER_DEFAULT = "1; mode=block"; - public static final String STRICT_TRANSPORT_SECURITY_HEADER_DEFAULT = "max-age=631138519"; //; includeSubDomains preload") - public static final String X_FRAME_OPTIONS_HEADER_DEFAULT = "DENY"; //SAMEORIGIN = ALLOW-FROM - public static final String X_CONTENT_TYPE_OPTIONS_HEADER_DEFAULT = "nosniff"; - public static final String REFERRER_POLICY_HEADER_DEFAULT = "no-referrer"; //no-referrer-when-downgrade = origin = origin-when-cross-origin = same-origin = strict-origin = strict-origin-when-cross-origin = unsafe-url - public static final String CONTENT_SECURITY_POLICY_HEADER_DEFAULT = "default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'"; - public static final String X_DOWNLOAD_OPTIONS_HEADER_DEFAULT = "noopen"; - public static final String X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER_DEFAULT = "none"; - - private String xssProtectionHeader = X_XSS_PROTECTION_HEADER_DEFAULT; - private String strictTransportSecurity = STRICT_TRANSPORT_SECURITY_HEADER_DEFAULT; - private String frameOptions = X_FRAME_OPTIONS_HEADER_DEFAULT; - private String contentTypeOptions = X_CONTENT_TYPE_OPTIONS_HEADER_DEFAULT; - private String referrerPolicy = REFERRER_POLICY_HEADER_DEFAULT; - private String contentSecurityPolicy = CONTENT_SECURITY_POLICY_HEADER_DEFAULT; - private String downloadOptions = X_DOWNLOAD_OPTIONS_HEADER_DEFAULT; - private String permittedCrossDomainPolicies = X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER_DEFAULT; - - public String getXssProtectionHeader() { - return xssProtectionHeader; - } - - public void setXssProtectionHeader(String xssProtectionHeader) { - this.xssProtectionHeader = xssProtectionHeader; - } - - public String getStrictTransportSecurity() { - return strictTransportSecurity; - } - - public void setStrictTransportSecurity(String strictTransportSecurity) { - this.strictTransportSecurity = strictTransportSecurity; - } - - public String getFrameOptions() { - return frameOptions; - } - - public void setFrameOptions(String frameOptions) { - this.frameOptions = frameOptions; - } - - public String getContentTypeOptions() { - return contentTypeOptions; - } - - public void setContentTypeOptions(String contentTypeOptions) { - this.contentTypeOptions = contentTypeOptions; - } - - public String getReferrerPolicy() { - return referrerPolicy; - } - - public void setReferrerPolicy(String referrerPolicy) { - this.referrerPolicy = referrerPolicy; - } - - public String getContentSecurityPolicy() { - return contentSecurityPolicy; - } - - public void setContentSecurityPolicy(String contentSecurityPolicy) { - this.contentSecurityPolicy = contentSecurityPolicy; - } - - public String getDownloadOptions() { - return downloadOptions; - } - - public void setDownloadOptions(String downloadOptions) { - this.downloadOptions = downloadOptions; - } - - public String getPermittedCrossDomainPolicies() { - return permittedCrossDomainPolicies; - } - - public void setPermittedCrossDomainPolicies(String permittedCrossDomainPolicies) { - this.permittedCrossDomainPolicies = permittedCrossDomainPolicies; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("SecureHeadersProperties{"); - sb.append("xssProtectionHeader='").append(xssProtectionHeader).append('\''); - sb.append(", strictTransportSecurity='").append(strictTransportSecurity).append('\''); - sb.append(", frameOptions='").append(frameOptions).append('\''); - sb.append(", contentTypeOptions='").append(contentTypeOptions).append('\''); - sb.append(", referrerPolicy='").append(referrerPolicy).append('\''); - sb.append(", contentSecurityPolicy='").append(contentSecurityPolicy).append('\''); - sb.append(", downloadOptions='").append(downloadOptions).append('\''); - sb.append(", permittedCrossDomainPolicies='").append(permittedCrossDomainPolicies).append('\''); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactory.java deleted file mode 100644 index 1b2dcaeb..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactory.java +++ /dev/null @@ -1,64 +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.filter.factory; - -import org.springframework.http.HttpHeaders; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -/** - * https://blog.appcanary.com/2017/http-security-headers.html - * @author Spencer Gibb - */ -public class SecureHeadersWebFilterFactory implements WebFilterFactory { - - public static final String X_XSS_PROTECTION_HEADER = "X-Xss-Protection"; - public static final String STRICT_TRANSPORT_SECURITY_HEADER = "Strict-Transport-Security"; - public static final String X_FRAME_OPTIONS_HEADER = "X-Frame-Options"; - public static final String X_CONTENT_TYPE_OPTIONS_HEADER = "X-Content-Type-Options"; - public static final String REFERRER_POLICY_HEADER = "Referrer-Policy"; - public static final String CONTENT_SECURITY_POLICY_HEADER = "Content-Security-Policy"; - public static final String X_DOWNLOAD_OPTIONS_HEADER = "X-Download-Options"; - public static final String X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER = "X-Permitted-Cross-Domain-Policies"; - - private final SecureHeadersProperties properties; - - public SecureHeadersWebFilterFactory(SecureHeadersProperties properties) { - this.properties = properties; - } - - @Override - public WebFilter apply(Tuple args) { - //TODO: allow args to override properties - - return (exchange, chain) -> { - HttpHeaders headers = exchange.getResponse().getHeaders(); - - headers.add(X_XSS_PROTECTION_HEADER, properties.getXssProtectionHeader()); - headers.add(STRICT_TRANSPORT_SECURITY_HEADER, properties.getStrictTransportSecurity()); - headers.add(X_FRAME_OPTIONS_HEADER, properties.getFrameOptions()); - headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, properties.getContentTypeOptions()); - headers.add(REFERRER_POLICY_HEADER, properties.getReferrerPolicy()); - headers.add(CONTENT_SECURITY_POLICY_HEADER, properties.getContentSecurityPolicy()); - headers.add(X_DOWNLOAD_OPTIONS_HEADER, properties.getDownloadOptions()); - headers.add(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, properties.getPermittedCrossDomainPolicies()); - - return chain.filter(exchange); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactory.java deleted file mode 100644 index d73c871d..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactory.java +++ /dev/null @@ -1,65 +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.filter.factory; - -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; -import org.springframework.web.util.UriTemplate; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE; - -/** - * @author Spencer Gibb - */ -public class SetPathWebFilterFactory implements WebFilterFactory { - - public static final String TEMPLATE_KEY = "template"; - - @Override - public List argNames() { - return Arrays.asList(TEMPLATE_KEY); - } - - @Override - @SuppressWarnings("unchecked") - public WebFilter apply(Tuple args) { - String template = args.getString(TEMPLATE_KEY); - UriTemplate uriTemplate = new UriTemplate(template); - - return (exchange, chain) -> { - Optional> variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE); - ServerHttpRequest req = exchange.getRequest(); - URI uri = uriTemplate.expand(variables.orElseGet(Collections::emptyMap)); - String newPath = uri.getPath(); - - ServerHttpRequest request = req.mutate() - .path(newPath) - .build(); - - return chain.filter(exchange.mutate().request(request).build()); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderWebFilterFactory.java deleted file mode 100644 index 1ecc2c67..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderWebFilterFactory.java +++ /dev/null @@ -1,47 +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.filter.factory; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class SetResponseHeaderWebFilterFactory implements WebFilterFactory { - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY, VALUE_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - final String header = args.getString(NAME_KEY); - final String value = args.getString(VALUE_KEY); - - return (exchange, chain) -> { - exchange.getResponse().getHeaders().set(header, value); - - return chain.filter(exchange); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactory.java deleted file mode 100644 index 96ec3115..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactory.java +++ /dev/null @@ -1,69 +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.filter.factory; - -import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; -import org.springframework.http.HttpStatus; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus; - -import reactor.core.publisher.Mono; - -import java.util.Arrays; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class SetStatusWebFilterFactory implements WebFilterFactory { - - public static final String STATUS_KEY = "status"; - - @Override - public List argNames() { - return Arrays.asList(STATUS_KEY); - } - - @Override - public WebFilter apply(Tuple args) { - String status = args.getRawString(STATUS_KEY); - final HttpStatus httpStatus = ServerWebExchangeUtils.parse(status); - - return (exchange, chain) -> { - - // option 1 (runs in filter order) - /*exchange.getResponse().beforeCommit(() -> { - exchange.getResponse().setStatusCode(finalStatus); - return Mono.empty(); - }); - return chain.filter(exchange);*/ - - // option 2 (runs in reverse filter order) - return chain.filter(exchange).then(Mono.fromRunnable(() -> { - // check not really needed, since it is guarded in setStatusCode, - // but it's a good example - if (!exchange.getResponse().isCommitted()) { - setResponseStatus(exchange, httpStatus); - } - })); - }; - } - -} 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 deleted file mode 100644 index dce80abe..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactories.java +++ /dev/null @@ -1,63 +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.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/filter/factory/WebFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactory.java deleted file mode 100644 index 25d81396..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactory.java +++ /dev/null @@ -1,39 +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.filter.factory; - -import org.springframework.cloud.gateway.support.ArgumentHints; -import org.springframework.cloud.gateway.support.NameUtils; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilter; - -/** - * @author Spencer Gibb - */ -@FunctionalInterface -public interface WebFilterFactory extends ArgumentHints { - - String NAME_KEY = "name"; - String VALUE_KEY = "value"; - - WebFilter apply(Tuple args); - - default String name() { - return NameUtils.normalizeFilterName(getClass()); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/KeyResolver.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/KeyResolver.java deleted file mode 100644 index 8d164bc4..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/KeyResolver.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.springframework.cloud.gateway.filter.ratelimit; - -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -//TODO: KeyResolver for exchange.getPrincipal().flatMap(principal -> {}) -public interface KeyResolver { - Mono resolve(ServerWebExchange exchange); -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/RateLimiter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/RateLimiter.java deleted file mode 100644 index cd85b1d8..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/RateLimiter.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.springframework.cloud.gateway.filter.ratelimit; - -/** - * @author Spencer Gibb - */ -public interface RateLimiter { - Response isAllowed(String id, int replenishRate, int burstCapacity); - - class Response { - private final boolean allowed; - private final long tokensRemaining; - - public Response(boolean allowed, long tokensRemaining) { - this.allowed = allowed; - this.tokensRemaining = tokensRemaining; - } - - public boolean isAllowed() { - return allowed; - } - - public long getTokensRemaining() { - return tokensRemaining; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("Response{"); - sb.append("allowed=").append(allowed); - sb.append(", tokensRemaining=").append(tokensRemaining); - sb.append('}'); - return sb.toString(); - } - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/RedisRateLimiter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/RedisRateLimiter.java deleted file mode 100644 index c3811ba8..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ratelimit/RedisRateLimiter.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.springframework.cloud.gateway.filter.ratelimit; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.core.script.RedisScript; - -import java.time.Instant; -import java.util.Arrays; -import java.util.List; - -/** - * See https://stripe.com/blog/rate-limiters and - * https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d#file-1-check_request_rate_limiter-rb-L11-L34 - * - * @author Spencer Gibb - */ -public class RedisRateLimiter implements RateLimiter { - private Log log = LogFactory.getLog(getClass()); - - private final StringRedisTemplate redisTemplate; - private final RedisScript script; - - public RedisRateLimiter(StringRedisTemplate redisTemplate, RedisScript script) { - this.redisTemplate = redisTemplate; - this.script = script; - } - - /** - * This uses a basic token bucket algorithm and relies on the fact that Redis scripts execute atomically. - * No other operations can run between fetching the count and writing the new count. - * @param replenishRate - * @param burstCapacity - * @param id - * @return - */ - @Override - //TODO: signature? params (tuple?). - public Response isAllowed(String id, int replenishRate, int burstCapacity) { - - try { - // Make a unique key per user. - String prefix = "request_rate_limiter." + id; - - // You need two Redis keys for Token Bucket. - List keys = Arrays.asList(prefix + ".tokens", prefix + ".timestamp"); - - // The arguments to the LUA script. time() returns unixtime in seconds. - Object[] args = new String[]{ replenishRate+"", burstCapacity +"", Instant.now().getEpochSecond()+"", "1"}; - // allowed, tokens_left = redis.eval(SCRIPT, keys, args) - List results = this.redisTemplate.execute(this.script, keys, args); - - boolean allowed = new Long(1L).equals(results.get(0)); - Long tokensLeft = (Long) results.get(1); - - Response response = new Response(allowed, tokensLeft); - - if (log.isDebugEnabled()) { - log.debug("response: "+response); - } - return response; - - } catch (Exception e) { - /* We don't want a hard dependency on Redis to allow traffic. - Make sure to set an alert so you know if this is happening too much. - Stripe's observed failure rate is 0.01%. */ - log.error("Error determining if user allowed from redis", e); - } - return new Response(true, -1); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java deleted file mode 100644 index 1b07dd6b..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java +++ /dev/null @@ -1,150 +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; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.cloud.gateway.filter.OrderedWebFilter; -import org.springframework.cloud.gateway.filter.factory.WebFilterFactory; -import org.springframework.cloud.gateway.route.Route; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; -import org.springframework.web.server.WebHandler; -import org.springframework.web.server.handler.WebHandlerDecorator; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; - -import reactor.core.publisher.Mono; - -/** - * WebHandler that delegates to a chain of {@link GlobalFilter} instances and - * {@link WebFilterFactory} instances then to the target {@link WebHandler}. - * - * @author Rossen Stoyanchev - * @author Spencer Gibb - * @since 0.1 - */ -public class FilteringWebHandler extends WebHandlerDecorator { - protected final Log logger = LogFactory.getLog(getClass()); - - private final List globalFilters; - - public FilteringWebHandler(List globalFilters) { - this(new EmptyWebHandler(), globalFilters); - } - - public FilteringWebHandler(WebHandler targetHandler, List globalFilters) { - super(targetHandler); - this.globalFilters = loadFilters(globalFilters); - } - - private static List loadFilters(List filters) { - return filters.stream() - .map(filter -> { - WebFilterAdapter webFilter = new WebFilterAdapter(filter); - if (filter instanceof Ordered) { - int order = ((Ordered) filter).getOrder(); - return new OrderedWebFilter(webFilter, order); - } - return webFilter; - }).collect(Collectors.toList()); - } - - /* TODO: relocate @EventListener(RefreshRoutesEvent.class) - void handleRefresh() { - this.combinedFiltersForRoute.clear(); - }*/ - - @Override - public Mono handle(ServerWebExchange exchange) { - Optional route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); - List webFilters = route.get().getWebFilters(); - - List combined = new ArrayList<>(this.globalFilters); - combined.addAll(webFilters); - //TODO: needed or cached? - AnnotationAwareOrderComparator.sort(combined); - - logger.debug("Sorted webFilterFactories: "+ combined); - - return new DefaultWebFilterChain(combined, getDelegate()).filter(exchange); - } - - private static class DefaultWebFilterChain implements WebFilterChain { - - private int index; - private final List filters; - private final WebHandler delegate; - - public DefaultWebFilterChain(List filters, WebHandler delegate) { - this.filters = filters; - this.delegate = delegate; - } - - @Override - public Mono filter(ServerWebExchange exchange) { - if (this.index < filters.size()) { - WebFilter filter = filters.get(this.index++); - return filter.filter(exchange, this); - } - else { - return this.delegate.handle(exchange); - } - } - } - - private static class WebFilterAdapter implements WebFilter { - - private final GlobalFilter delegate; - - public WebFilterAdapter(GlobalFilter delegate) { - this.delegate = delegate; - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - return this.delegate.filter(exchange, chain); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("WebFilterAdapter{"); - sb.append("delegate=").append(delegate); - sb.append('}'); - return sb.toString(); - } - } - - - private static class EmptyWebHandler implements WebHandler { - @Override - public Mono handle(ServerWebExchange exchange) { - return Mono.empty(); - } - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/NettyProxyWebHandler.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/NettyProxyWebHandler.java deleted file mode 100644 index ae35920a..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/NettyProxyWebHandler.java +++ /dev/null @@ -1,84 +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; - -import java.net.URI; -import java.util.Optional; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebHandler; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; - -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultHttpHeaders; -import io.netty.handler.codec.http.HttpMethod; -import reactor.core.publisher.Mono; -import reactor.ipc.netty.NettyPipeline; -import reactor.ipc.netty.http.client.HttpClient; - -/** - * @author Spencer Gibb - */ -public class NettyProxyWebHandler implements WebHandler { - - private final HttpClient httpClient; - - public NettyProxyWebHandler(HttpClient httpClient) { - this.httpClient = httpClient; - } - - @Override - public Mono handle(ServerWebExchange exchange) { - Optional requestUrl = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); - ServerHttpRequest request = exchange.getRequest(); - - final HttpMethod method = HttpMethod.valueOf(request.getMethod().toString()); - final String url = requestUrl.get().toString(); - - final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders(); - request.getHeaders().forEach(httpHeaders::set); - - return this.httpClient.request(method, url, req -> - req.options(NettyPipeline.SendOptions::flushOnEach) - .headers(httpHeaders) - .sendHeaders() // I shouldn't have to do this - .send(request.getBody() - .map(DataBuffer::asByteBuffer) - .map(Unpooled::wrappedBuffer))) - .doOnNext(res -> { - // Defer committing the response until all route filters have run - // Put client response as ServerWebExchange attribute and write response later WriteResponseFilter - exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res); - - ServerHttpResponse response = exchange.getResponse(); - // put headers and status so filters can modify the response - final HttpHeaders headers = new HttpHeaders(); - res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue())); - - response.getHeaders().putAll(headers); - response.setStatusCode(HttpStatus.valueOf(res.status().code())); - }).then(); - } -} 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/RoutePredicateHandlerMapping.java deleted file mode 100644 index 90cdac3a..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMapping.java +++ /dev/null @@ -1,114 +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; - -import java.util.function.Function; - -import org.springframework.cloud.gateway.route.RouteLocator; -import org.springframework.cloud.gateway.route.Route; -import org.springframework.web.reactive.handler.AbstractHandlerMapping; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebHandler; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { - - private final WebHandler webHandler; - private final RouteLocator routeLocator; - - public RoutePredicateHandlerMapping(WebHandler webHandler, RouteLocator routeLocator) { - this.webHandler = webHandler; - this.routeLocator = routeLocator; - - setOrder(1); - } - - @Override - protected Mono getHandlerInternal(ServerWebExchange exchange) { - exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName()); - - return lookupRoute(exchange) - .log() //name this - .flatMap((Function>) r -> { - if (logger.isDebugEnabled()) { - logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r); - } - - exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r); - return Mono.just(webHandler); - }).switchIfEmpty(Mono.empty().then(Mono.defer(() -> { - if (logger.isTraceEnabled()) { - logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]"); - } - return Mono.empty(); - }))); - } - - //TODO: get desc from factory? - private String getExchangeDesc(ServerWebExchange exchange) { - StringBuilder out = new StringBuilder(); - out.append("Exchange: "); - out.append(exchange.getRequest().getMethod()); - out.append(" "); - out.append(exchange.getRequest().getURI()); - return out.toString(); - } - - - protected Mono lookupRoute(ServerWebExchange exchange) { - return this.routeLocator.getRoutes() - .filter(route -> route.getPredicate().test(exchange)) - // .defaultIfEmpty() put a static Route not found - // or .switchIfEmpty() - // .switchIfEmpty(Mono.empty().log("noroute")) - .next() - //TODO: error handling - .map(route -> { - if (logger.isDebugEnabled()) { - logger.debug("RouteDefinition matched: " + route.getId()); - } - validateRoute(route, exchange); - return route; - }); - - /* TODO: trace logging - if (logger.isTraceEnabled()) { - logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); - }*/ - } - - /** - * Validate the given handler against the current request. - *

The default implementation is empty. Can be overridden in subclasses, - * for example to enforce specific preconditions expressed in URL mappings. - * @param route the Route object to validate - * @param exchange current exchange - * @throws Exception if validation failed - */ - @SuppressWarnings("UnusedParameters") - protected void validateRoute(Route route, ServerWebExchange exchange) { - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateFactory.java deleted file mode 100644 index 091eabee..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateFactory.java +++ /dev/null @@ -1,51 +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.time.ZonedDateTime; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory.parseZonedDateTime; - -/** - * @author Spencer Gibb - */ -public class AfterRoutePredicateFactory implements RoutePredicateFactory { - - public static final String DATETIME_KEY = "datetime"; - - @Override - public List argNames() { - return Collections.singletonList(DATETIME_KEY); - } - - @Override - public Predicate apply(Tuple args) { - final ZonedDateTime dateTime = parseZonedDateTime(args.getString(DATETIME_KEY)); - - return exchange -> { - 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/BeforeRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateFactory.java deleted file mode 100644 index a8345383..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateFactory.java +++ /dev/null @@ -1,52 +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.time.ZonedDateTime; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory.parseZonedDateTime; - -/** - * @author Spencer Gibb - */ -public class BeforeRoutePredicateFactory implements RoutePredicateFactory { - - public static final String DATETIME_KEY = "datetime"; - - @Override - public List argNames() { - return Collections.singletonList(DATETIME_KEY); - } - - @Override - public Predicate apply(Tuple args) { - final ZonedDateTime dateTime = parseZonedDateTime(args.getString(DATETIME_KEY)); - - return exchange -> { - 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/BetweenRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateFactory.java deleted file mode 100644 index 7aaa1b26..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateFactory.java +++ /dev/null @@ -1,66 +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.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.util.Assert; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class BetweenRoutePredicateFactory implements RoutePredicateFactory { - - public static final String DATETIME1_KEY = "datetime1"; - public static final String DATETIME2_KEY = "datetime2"; - - @Override - public Predicate apply(Tuple args) { - //TODO: is ZonedDateTime the right thing to use? - final ZonedDateTime dateTime1 = parseZonedDateTime(args.getString(DATETIME1_KEY)); - final ZonedDateTime dateTime2 = parseZonedDateTime(args.getString(DATETIME2_KEY)); - Assert.isTrue(dateTime1.isBefore(dateTime2), args.getString(DATETIME1_KEY) + - " must be before " + args.getString(DATETIME2_KEY)); - - return exchange -> { - final ZonedDateTime now = ZonedDateTime.now(); - return now.isAfter(dateTime1) && now.isBefore(dateTime2); - }; - } - - public static ZonedDateTime parseZonedDateTime(String dateString) { - ZonedDateTime dateTime; - try { - long epoch = Long.parseLong(dateString); - - dateTime = Instant.ofEpochMilli(epoch).atOffset(ZoneOffset.ofTotalSeconds(0)) - .toZonedDateTime(); - } catch (NumberFormatException e) { - // try ZonedDateTime instead - dateTime = ZonedDateTime.parse(dateString); - } - - return dateTime; - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactory.java deleted file mode 100644 index e6b63d4b..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactory.java +++ /dev/null @@ -1,56 +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.Arrays; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.http.HttpCookie; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class CookieRoutePredicateFactory implements RoutePredicateFactory { - - public static final String NAME_KEY = "name"; - public static final String REGEXP_KEY = "regexp"; - - @Override - public List argNames() { - return Arrays.asList(NAME_KEY, REGEXP_KEY); - } - - @Override - public Predicate apply(Tuple args) { - String name = args.getString(NAME_KEY); - String regexp = args.getString(REGEXP_KEY); - - return exchange -> { - List cookies = exchange.getRequest().getCookies().get(name); - for (HttpCookie cookie : cookies) { - if (cookie.getValue().matches(regexp)) { - return true; - } - } - return false; - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java deleted file mode 100644 index 44fc4574..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java +++ /dev/null @@ -1,55 +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.Arrays; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class HeaderRoutePredicateFactory implements RoutePredicateFactory { - - public static final String HEADER_KEY = "header"; - public static final String REGEXP_KEY = "regexp"; - - @Override - public List argNames() { - return Arrays.asList(HEADER_KEY, REGEXP_KEY); - } - - @Override - public Predicate apply(Tuple args) { - String header = args.getString(HEADER_KEY); - String regexp = args.getString(REGEXP_KEY); - - return exchange -> { - List values = exchange.getRequest().getHeaders().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/HostRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactory.java deleted file mode 100644 index e77a0df6..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactory.java +++ /dev/null @@ -1,54 +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.Collections; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class HostRoutePredicateFactory implements RoutePredicateFactory { - - private PathMatcher pathMatcher = new AntPathMatcher("."); - - public void setPathMatcher(PathMatcher pathMatcher) { - this.pathMatcher = pathMatcher; - } - - @Override - public List argNames() { - return Collections.singletonList(PATTERN_KEY); - } - - @Override - public Predicate apply(Tuple args) { - String pattern = args.getString(PATTERN_KEY); - - return exchange -> { - String host = exchange.getRequest().getHeaders().getFirst("Host"); - return this.pathMatcher.match(pattern, host); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicateFactory.java deleted file mode 100644 index 116d645e..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicateFactory.java +++ /dev/null @@ -1,48 +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.Arrays; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.http.HttpMethod; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class MethodRoutePredicateFactory implements RoutePredicateFactory { - - public static final String METHOD_KEY = "method"; - - @Override - public List argNames() { - return Arrays.asList(METHOD_KEY); - } - - @Override - public Predicate apply(Tuple args) { - String method = args.getString(METHOD_KEY); - return exchange -> { - HttpMethod requestMethod = exchange.getRequest().getMethod(); - return requestMethod.matches(method); - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java deleted file mode 100644 index be0e45e1..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java +++ /dev/null @@ -1,71 +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.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.util.pattern.PathPattern; -import org.springframework.web.util.pattern.PathPatternParser; - -import static org.springframework.cloud.gateway.handler.support.RoutePredicateFactoryUtils.traceMatch; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE; - -/** - * @author Spencer Gibb - */ -public class PathRoutePredicateFactory implements RoutePredicateFactory { - - private PathPatternParser pathPatternParser = new PathPatternParser(); - - public void setPathPatternParser(PathPatternParser pathPatternParser) { - this.pathPatternParser = pathPatternParser; - } - - @Override - public List argNames() { - return Collections.singletonList(PATTERN_KEY); - } - - @Override - public Predicate apply(Tuple args) { - String unparsedPattern = args.getString(PATTERN_KEY); - PathPattern pattern; - synchronized (this.pathPatternParser) { - pattern = this.pathPatternParser.parse(unparsedPattern); - } - - return exchange -> { - String path = exchange.getRequest().getURI().getPath(); - boolean match = pattern.matches(path); - traceMatch("Pattern", pattern.getPatternString(), path, match); - if (match) { - Map uriTemplateVariables = pattern.matchAndExtract(path); - exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); - return true; - } - else { - return false; - } - }; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PredicateDefinition.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PredicateDefinition.java deleted file mode 100644 index f202b9d4..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/PredicateDefinition.java +++ /dev/null @@ -1,101 +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.LinkedHashMap; -import java.util.Map; -import java.util.Objects; - -import javax.validation.ValidationException; -import javax.validation.constraints.NotNull; - -import org.springframework.cloud.gateway.support.NameUtils; -import org.springframework.validation.annotation.Validated; - -import static org.springframework.util.StringUtils.tokenizeToStringArray; - -/** - * @author Spencer Gibb - */ -@Validated -public class PredicateDefinition { - @NotNull - private String name; - private Map args = new LinkedHashMap<>(); - - public PredicateDefinition() { - } - - public PredicateDefinition(String text) { - int eqIdx = text.indexOf("="); - if (eqIdx <= 0) { - throw new ValidationException("Unable to parse PredicateDefinition text '" + text + "'" + - ", must be of the form name=value"); - } - setName(text.substring(0, eqIdx)); - - String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ","); - - for (int i=0; i < args.length; i++) { - this.args.put(NameUtils.generateName(i), args[i]); - } - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map getArgs() { - return args; - } - - public void setArgs(Map args) { - this.args = args; - } - - public void addArg(String key, String value) { - this.args.put(key, value); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PredicateDefinition that = (PredicateDefinition) o; - return Objects.equals(name, that.name) && - Objects.equals(args, that.args); - } - - @Override - public int hashCode() { - return Objects.hash(name, args); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("PredicateDefinition{"); - sb.append("name='").append(name).append('\''); - sb.append(", args=").append(args); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactory.java deleted file mode 100644 index adb86ab8..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactory.java +++ /dev/null @@ -1,67 +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.Arrays; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class QueryRoutePredicateFactory implements RoutePredicateFactory { - - public static final String PARAM_KEY = "param"; - public static final String REGEXP_KEY = "regexp"; - - @Override - public List argNames() { - return Arrays.asList(PARAM_KEY, REGEXP_KEY); - } - - @Override - public boolean validateArgs() { - return false; - } - - @Override - public Predicate apply(Tuple args) { - validateMin(1, args); - String param = args.getString(PARAM_KEY); - - return exchange -> { - if (!args.hasFieldName(REGEXP_KEY)) { - // check existence of header - return exchange.getRequest().getQueryParams().containsKey(param); - } - - String regexp = args.getString(REGEXP_KEY); - - List values = exchange.getRequest().getQueryParams().get(param); - 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/RemoteAddrRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicateFactory.java deleted file mode 100644 index 591f8288..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicateFactory.java +++ /dev/null @@ -1,85 +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.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.support.SubnetUtils; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class RemoteAddrRoutePredicateFactory implements RoutePredicateFactory { - - private static final Log log = LogFactory.getLog(RemoteAddrRoutePredicateFactory.class); - - @Override - public Predicate apply(Tuple args) { - validate(1, args); - - List sources = new ArrayList<>(); - if (args != null) { - for (Object arg : args.getValues()) { - addSource(sources, (String) arg); - } - } - - return exchange -> { - InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress(); - if (remoteAddress != null) { - String hostAddress = remoteAddress.getAddress().getHostAddress(); - String host = exchange.getRequest().getURI().getHost(); - - if (!hostAddress.equals(host)) { - log.warn("Remote addresses didn't match " + hostAddress + " != " + host); - } - - for (SubnetUtils source : sources) { - if (source.getInfo().isInRange(hostAddress)) { - return true; - } - } - } - - return false; - }; - } - - private void addSource(List sources, String source) { - boolean inclusiveHostCount = false; - if (!source.contains("/")) { // no netmask, add default - source = source + "/32"; - } - if (source.endsWith("/32")) { - //http://stackoverflow.com/questions/2942299/converting-cidr-address-to-subnet-mask-and-network-address#answer-6858429 - inclusiveHostCount = true; - } - //TODO: howto support ipv6 as well? - SubnetUtils subnetUtils = new SubnetUtils(source); - subnetUtils.setInclusiveHostCount(inclusiveHostCount); - sources.add(subnetUtils); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicateFactory.java deleted file mode 100644 index 7fc39888..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicateFactory.java +++ /dev/null @@ -1,40 +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.function.Predicate; - -import org.springframework.cloud.gateway.support.ArgumentHints; -import org.springframework.cloud.gateway.support.NameUtils; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -@FunctionalInterface -public interface RoutePredicateFactory extends ArgumentHints { - String PATTERN_KEY = "pattern"; - - Predicate apply(Tuple args); - - default String name() { - return NameUtils.normalizePredicateName(getClass()); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicates.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicates.java deleted file mode 100644 index 8622a172..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicates.java +++ /dev/null @@ -1,63 +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 org.springframework.web.server.ServerWebExchange; - -import java.util.function.Predicate; - -import static org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory.METHOD_KEY; -import static org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory.PATTERN_KEY; -import static org.springframework.tuple.TupleBuilder.tuple; - -/** - * @author Spencer Gibb - */ -public class RoutePredicates { - - //TODO: add support for AfterRoutePredicateFactory - - //TODO: add support for BeforeRoutePredicateFactory - - //TODO: add support for BetweenRoutePredicateFactory - - //TODO: add support for CookieRoutePredicateFactory - - //TODO: add support for RoutePredicates - - //TODO: add support for HeaderRoutePredicateFactory - - public static Predicate host(String pattern) { - return new HostRoutePredicateFactory().apply(tuple().of(PATTERN_KEY, pattern)); - } - - public static Predicate method(String method) { - return new MethodRoutePredicateFactory().apply(tuple().of(METHOD_KEY, method)); - } - - public static Predicate path(String pattern) { - return new PathRoutePredicateFactory().apply(tuple().of(PATTERN_KEY, pattern)); - } - - //TODO: add support for PredicateDefinition - - //TODO: add support for QueryRoutePredicateFactory - - //TODO: add support for RemoteAddrRoutePredicateFactory - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/support/RoutePredicateFactoryUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/support/RoutePredicateFactoryUtils.java deleted file mode 100644 index a63dc0db..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/support/RoutePredicateFactoryUtils.java +++ /dev/null @@ -1,37 +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.support; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; - -/** - * @author Spencer Gibb - */ -public class RoutePredicateFactoryUtils { - private static final Log logger = LogFactory.getLog(RoutePredicateFactory.class); - - public static void traceMatch(String prefix, Object desired, Object actual, boolean match) { - if (logger.isTraceEnabled()) { - String message = String.format("%s \"%s\" %s against value \"%s\"", - prefix, desired, match ? "matches" : "does not match", actual); - logger.trace(message); - } - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CachingRouteDefinitionLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CachingRouteDefinitionLocator.java deleted file mode 100644 index dcbfcb27..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CachingRouteDefinitionLocator.java +++ /dev/null @@ -1,61 +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.route; - -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import org.springframework.context.event.EventListener; -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public class CachingRouteDefinitionLocator implements RouteDefinitionLocator { - - private final RouteDefinitionLocator delegate; - private final AtomicReference> cachedRoutes = new AtomicReference<>(); - - public CachingRouteDefinitionLocator(RouteDefinitionLocator delegate) { - this.delegate = delegate; - this.cachedRoutes.compareAndSet(null, collectRoutes()); - } - - @Override - public Flux getRouteDefinitions() { - return Flux.fromIterable(this.cachedRoutes.get()); - } - - /** - * Sets the new routes - * @return old routes - */ - public Flux refresh() { - return Flux.fromIterable(this.cachedRoutes.getAndUpdate( - routes -> CachingRouteDefinitionLocator.this.collectRoutes())); - } - - private List collectRoutes() { - return this.delegate.getRouteDefinitions().collectList().block(); - } - - @EventListener(RefreshRoutesEvent.class) - /* for testing */ void handleRefresh() { - refresh(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java deleted file mode 100644 index 1d69cb25..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CachingRouteLocator.java +++ /dev/null @@ -1,65 +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.route; - -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import org.springframework.context.event.EventListener; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public class CachingRouteLocator implements RouteLocator { - - private final RouteLocator delegate; - private final AtomicReference> cachedRoutes = new AtomicReference<>(); - - public CachingRouteLocator(RouteLocator delegate) { - this.delegate = delegate; - this.cachedRoutes.compareAndSet(null, collectRoutes()); - } - - @Override - public Flux getRoutes() { - return Flux.fromIterable(this.cachedRoutes.get()); - } - - /** - * Sets the new routes - * @return old routes - */ - public Flux refresh() { - return Flux.fromIterable(this.cachedRoutes.getAndUpdate( - routes -> CachingRouteLocator.this.collectRoutes())); - } - - private List collectRoutes() { - List routes = this.delegate.getRoutes().collectList().block(); - AnnotationAwareOrderComparator.sort(routes); - return routes; - } - - @EventListener(RefreshRoutesEvent.class) - /* for testing */ void handleRefresh() { - refresh(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java deleted file mode 100644 index aefc17f4..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteDefinitionLocator.java +++ /dev/null @@ -1,37 +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.route; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator { - - private final Flux delegates; - - public CompositeRouteDefinitionLocator(Flux delegates) { - this.delegates = delegates; - } - - @Override - public Flux getRouteDefinitions() { - return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteLocator.java deleted file mode 100644 index c7aef785..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/CompositeRouteLocator.java +++ /dev/null @@ -1,37 +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.route; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public class CompositeRouteLocator implements RouteLocator { - - private final Flux delegates; - - public CompositeRouteLocator(Flux delegates) { - this.delegates = delegates; - } - - @Override - public Flux getRoutes() { - return this.delegates.flatMap(RouteLocator::getRoutes); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/InMemoryRouteDefinitionRepository.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/InMemoryRouteDefinitionRepository.java deleted file mode 100644 index 8cb5c87d..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/InMemoryRouteDefinitionRepository.java +++ /dev/null @@ -1,60 +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.route; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.cloud.gateway.support.NotFoundException; - -import static java.util.Collections.synchronizedMap; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository { - - private final Map routes = synchronizedMap(new LinkedHashMap()); - - @Override - public Mono save(Mono route) { - return route.flatMap( r -> { - routes.put(r.getId(), r); - return Mono.empty(); - }); - } - - @Override - public Mono delete(Mono routeId) { - return routeId.flatMap(id -> { - if (routes.containsKey(id)) { - routes.remove(id); - return Mono.empty(); - } - return Mono.error(new NotFoundException("RouteDefinition not found: "+routeId)); - }); - } - - @Override - public Flux getRouteDefinitions() { - return Flux.fromIterable(routes.values()); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RefreshRoutesEvent.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RefreshRoutesEvent.java deleted file mode 100644 index 1827f284..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RefreshRoutesEvent.java +++ /dev/null @@ -1,35 +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.route; - -import org.springframework.context.ApplicationEvent; - -/** - * @author Spencer Gibb - */ -public class RefreshRoutesEvent extends ApplicationEvent { - - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - */ - public RefreshRoutesEvent(Object source) { - super(source); - } -} 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 deleted file mode 100644 index e0c3fc32..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Route.java +++ /dev/null @@ -1,177 +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.route; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.function.Predicate; - -import org.springframework.core.Ordered; -import org.springframework.util.Assert; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; - -/** - * @author Spencer Gibb - */ -public class Route implements Ordered { - - private final String id; - - private final URI uri; - - private final int order; - - private final Predicate predicate; - - private final List webFilters; - - public static Builder builder() { - return new Builder(); - } - - public static Builder builder(RouteDefinition routeDefinition) { - return new Builder() - .id(routeDefinition.getId()) - .uri(routeDefinition.getUri()) - .order(routeDefinition.getOrder()); - } - - public Route(String id, URI uri, int order, Predicate predicate, List webFilters) { - this.id = id; - this.uri = uri; - this.order = order; - this.predicate = predicate; - this.webFilters = webFilters; - } - - public static class Builder { - private String id; - - private URI uri; - - private int order = 0; - - private Predicate predicate; - - private List webFilters = new ArrayList<>(); - - private Builder() {} - - public Builder id(String id) { - this.id = id; - return this; - } - - public Builder uri(String uri) { - this.uri = URI.create(uri); - return this; - } - - public Builder order(int order) { - this.order = order; - return this; - } - - public Builder uri(URI uri) { - this.uri = uri; - return this; - } - - public Builder predicate(Predicate predicate) { - this.predicate = predicate; - return this; - } - - public Builder webFilters(List webFilters) { - this.webFilters = webFilters; - return this; - } - - public Builder add(WebFilter webFilter) { - this.webFilters.add(webFilter); - return this; - } - - public Builder addAll(Collection webFilters) { - this.webFilters.addAll(webFilters); - return this; - } - - public Route build() { - Assert.notNull(this.id, "id can not be null"); - Assert.notNull(this.uri, "uri can not be null"); - //TODO: Assert.notNull(this.predicate, "predicate can not be null"); - - return new Route(this.id, this.uri, this.order, this.predicate, this.webFilters); - } - } - - public String getId() { - return this.id; - } - - public URI getUri() { - return this.uri; - } - - public int getOrder() { - return order; - } - - public Predicate getPredicate() { - return this.predicate; - } - - public List getWebFilters() { - return Collections.unmodifiableList(this.webFilters); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Route route = (Route) o; - return Objects.equals(id, route.id) && - Objects.equals(uri, route.uri) && - Objects.equals(order, route.order) && - Objects.equals(predicate, route.predicate) && - Objects.equals(webFilters, route.webFilters); - } - - @Override - public int hashCode() { - return Objects.hash(id, uri, predicate, webFilters); - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("Route{"); - sb.append("id='").append(id).append('\''); - sb.append(", uri=").append(uri); - sb.append(", order=").append(order); - sb.append(", predicate=").append(predicate); - sb.append(", webFilters=").append(webFilters); - sb.append('}'); - return sb.toString(); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java deleted file mode 100644 index 6fbece81..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinition.java +++ /dev/null @@ -1,142 +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.route; - -import org.hibernate.validator.constraints.NotEmpty; -import org.springframework.cloud.gateway.filter.FilterDefinition; -import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; -import org.springframework.validation.annotation.Validated; - -import javax.validation.Valid; -import javax.validation.ValidationException; -import javax.validation.constraints.NotNull; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.UUID; - -import static org.springframework.util.StringUtils.tokenizeToStringArray; - -/** - * @author Spencer Gibb - */ -@Validated -public class RouteDefinition { - @NotEmpty - private String id = UUID.randomUUID().toString(); - - @NotEmpty - @Valid - private List predicates = new ArrayList<>(); - - @Valid - private List filters = new ArrayList<>(); - - @NotNull - private URI uri; - - private int order = 0; - - public RouteDefinition() {} - - public RouteDefinition(String text) { - int eqIdx = text.indexOf("="); - if (eqIdx <= 0) { - throw new ValidationException("Unable to parse RouteDefinition text '" + text + "'" + - ", must be of the form name=value"); - } - - setId(text.substring(0, eqIdx)); - - String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ","); - - setUri(URI.create(args[0])); - - for (int i=1; i < args.length; i++) { - this.predicates.add(new PredicateDefinition(args[i])); - } - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public List getPredicates() { - return predicates; - } - - public void setPredicates(List predicates) { - this.predicates = predicates; - } - - public List getFilters() { - return filters; - } - - public void setFilters(List filters) { - this.filters = filters; - } - - public URI getUri() { - return uri; - } - - public void setUri(URI uri) { - this.uri = uri; - } - - public int getOrder() { - return order; - } - - public void setOrder(int order) { - this.order = order; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RouteDefinition routeDefinition = (RouteDefinition) o; - return Objects.equals(id, routeDefinition.id) && - Objects.equals(predicates, routeDefinition.predicates) && - Objects.equals(order, routeDefinition.order) && - Objects.equals(uri, routeDefinition.uri); - } - - @Override - public int hashCode() { - return Objects.hash(id, predicates, uri); - } - - @Override - public String toString() { - return "RouteDefinition{" + - "id='" + id + '\'' + - ", predicates=" + predicates + - ", filters=" + filters + - ", uri=" + uri + - ", order=" + order + - '}'; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionLocator.java deleted file mode 100644 index e27dacd6..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionLocator.java +++ /dev/null @@ -1,28 +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.route; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public interface RouteDefinitionLocator { - - Flux getRouteDefinitions(); -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRepository.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRepository.java deleted file mode 100644 index 16b6cb3c..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRepository.java +++ /dev/null @@ -1,24 +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.route; - -/** - * @author Spencer Gibb - */ -public interface RouteDefinitionRepository extends RouteDefinitionLocator, RouteDefinitionWriter { -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java deleted file mode 100644 index 6fbea4fc..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java +++ /dev/null @@ -1,222 +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.route; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.config.GatewayProperties; -import org.springframework.cloud.gateway.filter.FilterDefinition; -import org.springframework.cloud.gateway.filter.OrderedWebFilter; -import org.springframework.cloud.gateway.filter.factory.WebFilterFactory; -import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; -import org.springframework.cloud.gateway.support.ArgumentHints; -import org.springframework.cloud.gateway.support.NameUtils; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.tuple.Tuple; -import org.springframework.tuple.TupleBuilder; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; - -import reactor.core.publisher.Flux; - -/** - * {@link RouteLocator} that loads routes from a {@link RouteDefinitionLocator} - * @author Spencer Gibb - */ -public class RouteDefinitionRouteLocator implements RouteLocator { - protected final Log logger = LogFactory.getLog(getClass()); - - private final RouteDefinitionLocator routeDefinitionLocator; - private final Map predicates = new LinkedHashMap<>(); - private final Map webFilterFactories = new HashMap<>(); - private final GatewayProperties gatewayProperties; - - public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator, - List predicates, - List webFilterFactories, - GatewayProperties gatewayProperties) { - this.routeDefinitionLocator = routeDefinitionLocator; - initFactories(predicates); - webFilterFactories.forEach(factory -> this.webFilterFactories.put(factory.name(), factory)); - this.gatewayProperties = gatewayProperties; - } - - private void initFactories(List predicates) { - predicates.forEach(factory -> { - String key = factory.name(); - if (this.predicates.containsKey(key)) { - this.logger.warn("A RoutePredicateFactory named "+ key - + " already exists, class: " + this.predicates.get(key) - + ". It will be overwritten."); - } - this.predicates.put(key, factory); - if (logger.isInfoEnabled()) { - logger.info("Loaded RoutePredicateFactory [" + key + "]"); - } - }); - } - - @Override - public Flux getRoutes() { - return this.routeDefinitionLocator.getRouteDefinitions() - .map(this::convertToRoute) - //TODO: error handling - .map(route -> { - if (logger.isDebugEnabled()) { - logger.debug("RouteDefinition matched: " + route.getId()); - } - return route; - }); - - - /* TODO: trace logging - if (logger.isTraceEnabled()) { - logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); - }*/ - } - - private Route convertToRoute(RouteDefinition routeDefinition) { - Predicate predicate = combinePredicates(routeDefinition); - List webFilters = getFilters(routeDefinition); - - return Route.builder(routeDefinition) - .predicate(predicate) - .webFilters(webFilters) - .build(); - } - - private List loadWebFilters(String id, List filterDefinitions) { - List filters = filterDefinitions.stream() - .map(definition -> { - WebFilterFactory filter = this.webFilterFactories.get(definition.getName()); - if (filter == null) { - throw new IllegalArgumentException("Unable to find WebFilterFactory with name " + definition.getName()); - } - Map args = definition.getArgs(); - if (logger.isDebugEnabled()) { - logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName()); - } - - Tuple tuple = getTuple(filter, args); - - return filter.apply(tuple); - }) - .collect(Collectors.toList()); - - ArrayList ordered = new ArrayList<>(filters.size()); - for (int i = 0; i < filters.size(); i++) { - ordered.add(new OrderedWebFilter(filters.get(i), i+1)); - } - - return ordered; - } - - private Tuple getTuple(ArgumentHints hasArguments, Map args) { - TupleBuilder builder = TupleBuilder.tuple(); - - List argNames = hasArguments.argNames(); - if (!argNames.isEmpty()) { - // ensure size is the same for key replacement later - if (hasArguments.validateArgs() && args.size() != argNames.size()) { - throw new IllegalArgumentException("Wrong number of arguments. Expected " + argNames - + " " + argNames + ". Found " + args.size() + " " + args + "'"); - } - } - - int entryIdx = 0; - for (Map.Entry entry : args.entrySet()) { - String key = entry.getKey(); - - // RoutePredicateFactory has name hints and this has a fake key name - // replace with the matching key hint - if (key.startsWith(NameUtils.GENERATED_NAME_PREFIX) && !argNames.isEmpty() - && entryIdx < args.size()) { - key = argNames.get(entryIdx); - } - - builder.put(key, entry.getValue()); - entryIdx++; - } - - Tuple tuple = builder.build(); - - if (hasArguments.validateArgs()) { - for (String name : argNames) { - if (!tuple.hasFieldName(name)) { - throw new IllegalArgumentException("Missing argument '" + name + "'. Given " + tuple); - } - } - } - return tuple; - } - - private List getFilters(RouteDefinition routeDefinition) { - List filters = new ArrayList<>(); - - //TODO: support option to apply defaults after route specific filters? - if (!this.gatewayProperties.getDefaultFilters().isEmpty()) { - filters.addAll(loadWebFilters("defaultFilters", - this.gatewayProperties.getDefaultFilters())); - } - - if (!routeDefinition.getFilters().isEmpty()) { - filters.addAll(loadWebFilters(routeDefinition.getId(), routeDefinition.getFilters())); - } - - AnnotationAwareOrderComparator.sort(filters); - return filters; - } - - private Predicate combinePredicates(RouteDefinition routeDefinition) { - List predicates = routeDefinition.getPredicates(); - Predicate predicate = lookup(routeDefinition, predicates.get(0)); - - for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) { - Predicate found = lookup(routeDefinition, andPredicate); - predicate = predicate.and(found); - } - - return predicate; - } - - private Predicate lookup(RouteDefinition routeDefinition, PredicateDefinition predicate) { - RoutePredicateFactory found = this.predicates.get(predicate.getName()); - if (found == null) { - throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name " + predicate.getName()); - } - Map args = predicate.getArgs(); - if (logger.isDebugEnabled()) { - logger.debug("RouteDefinition " + routeDefinition.getId() + " applying " - + args + " to " + predicate.getName()); - } - - Tuple tuple = getTuple(found, args); - - return found.apply(tuple); - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionWriter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionWriter.java deleted file mode 100644 index 225a541b..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionWriter.java +++ /dev/null @@ -1,31 +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.route; - -import org.springframework.cloud.gateway.route.RouteDefinition; -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public interface RouteDefinitionWriter { - - Mono save(Mono route); - - Mono delete(Mono routeId); -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteLocator.java deleted file mode 100644 index a17936c4..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteLocator.java +++ /dev/null @@ -1,29 +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.route; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -//TODO: rename to Routes? -public interface RouteLocator { - - Flux getRoutes(); -} 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 deleted file mode 100644 index 4f996069..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/Routes.java +++ /dev/null @@ -1,158 +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.route; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.function.Predicate; - -import org.springframework.cloud.gateway.filter.factory.WebFilterFactories; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; - -import reactor.core.publisher.Flux; - -/** - * @author Spencer Gibb - */ -public class Routes { - - public static LocatorBuilder locator() { - return new LocatorBuilder(); - } - - public static class LocatorBuilder { - - private List routes = new ArrayList<>(); - - public RouteSpec route(String id) { - return new RouteSpec(this).id(id); - } - - private void add(Route route) { - this.routes.add(route); - } - - public RouteLocator build() { - return () -> Flux.fromIterable(this.routes); - } - - } - - public static class RouteSpec { - private final Route.Builder builder = Route.builder(); - private final LocatorBuilder locatorBuilder; - - private RouteSpec(LocatorBuilder locatorBuilder) { - this.locatorBuilder = locatorBuilder; - } - - public RouteSpec id(String id) { - this.builder.id(id); - return this; - } - - public RouteSpec order(int order) { - this.builder.order(order); - return this; - } - - public PredicateSpec uri(String uri) { - this.builder.uri(uri); - return predicateBuilder(); - } - - public PredicateSpec uri(URI uri) { - this.builder.uri(uri); - return predicateBuilder(); - } - - private PredicateSpec predicateBuilder() { - return new PredicateSpec(this.builder, this.locatorBuilder); - } - - } - - public static class PredicateSpec { - - private final Route.Builder routeBuilder; - private LocatorBuilder locatorBuilder; - - private PredicateSpec(Route.Builder routeBuilder, LocatorBuilder locatorBuilder) { - this.routeBuilder = routeBuilder; - this.locatorBuilder = locatorBuilder; - } - - /* TODO: has and, or & negate of Predicate with terminal andFilters()? - public RoutePredicateBuilder predicate() { - } - // this goes in new class - public RoutePredicateBuilder host(String pattern) { - Predicate predicate = RoutePredicates.host(pattern); - }*/ - - public WebFilterSpec predicate(Predicate predicate) { - this.routeBuilder.predicate(predicate); - return webFilterBuilder(); - } - - private WebFilterSpec webFilterBuilder() { - return new WebFilterSpec(this.routeBuilder, this.locatorBuilder); - } - - } - - public static class WebFilterSpec { - private Route.Builder builder; - private LocatorBuilder locatorBuilder; - - public WebFilterSpec(Route.Builder routeBuilder, LocatorBuilder locatorBuilder) { - this.builder = routeBuilder; - this.locatorBuilder = locatorBuilder; - } - - public WebFilterSpec webFilters(List webFilters) { - this.builder.webFilters(webFilters); - return this; - } - - public WebFilterSpec add(WebFilter webFilter) { - this.builder.add(webFilter); - return this; - } - - public WebFilterSpec addAll(Collection webFilters) { - this.builder.addAll(webFilters); - return this; - } - - public WebFilterSpec addResponseHeader(String headerName, String headerValue) { - return add(WebFilterFactories.addResponseHeader(headerName, headerValue)); - } - - // TODO: build()? - public LocatorBuilder and() { - Route route = this.builder.build(); - this.locatorBuilder.add(route); - return this.locatorBuilder; - } - } - -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ArgumentHints.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ArgumentHints.java deleted file mode 100644 index 852464c7..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ArgumentHints.java +++ /dev/null @@ -1,57 +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.support; - -import org.springframework.tuple.Tuple; -import org.springframework.util.Assert; - -import java.util.Collections; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public interface ArgumentHints { - - /** - * Returns hints about the number of args and the order for shortcut parsing. - * @return - */ - default List argNames() { - return Collections.emptyList(); - } - - /** - * Validate supplied argument size against {@see #argNames} size. - * Useful for variable arg predicates. - * @return - */ - default boolean validateArgs() { - return true; - } - - default void validate(int requiredSize, Tuple args) { - Assert.isTrue(args != null && args.size() == requiredSize, - "args must have "+ requiredSize +" entry(s)"); - } - - default void validateMin(int minSize, Tuple args) { - Assert.isTrue(args != null && args.size() >= minSize, - "args must have at least "+ minSize +" entry(s)"); - } -} 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 deleted file mode 100644 index 1f31e7fc..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NameUtils.java +++ /dev/null @@ -1,40 +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.support; - -import org.springframework.cloud.gateway.filter.factory.WebFilterFactory; -import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; - -/** - * @author Spencer Gibb - */ -public class NameUtils { - public static final String GENERATED_NAME_PREFIX = "_genkey_"; - - public static String generateName(int i) { - return GENERATED_NAME_PREFIX + i; - } - - public static String normalizePredicateName(Class clazz) { - return clazz.getSimpleName().replace(RoutePredicateFactory.class.getSimpleName(), ""); - } - - public static String normalizeFilterName(Class clazz) { - return clazz.getSimpleName().replace(WebFilterFactory.class.getSimpleName(), ""); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NotFoundException.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NotFoundException.java deleted file mode 100644 index b8e83aae..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/NotFoundException.java +++ /dev/null @@ -1,31 +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.support; - -/** - * @author Spencer Gibb - */ -public class NotFoundException extends RuntimeException { - public NotFoundException(String message) { - super(message); - } - - public NotFoundException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java deleted file mode 100644 index 8ba59f5d..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java +++ /dev/null @@ -1,63 +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.support; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.http.HttpStatus; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author Spencer Gibb - */ -public class ServerWebExchangeUtils { - - private static final Log logger = LogFactory.getLog(ServerWebExchangeUtils.class); - - public static final String URI_TEMPLATE_VARIABLES_ATTRIBUTE = qualify("uriTemplateVariables"); - - public static final String CLIENT_RESPONSE_ATTR = qualify("webHandlerClientResponse"); - public static final String GATEWAY_ROUTE_ATTR = qualify("gatewayRoute"); - public static final String GATEWAY_REQUEST_URL_ATTR = qualify("gatewayRequestUrl"); - public static final String GATEWAY_HANDLER_MAPPER_ATTR = qualify("gatewayHandlerMapper"); - - private static String qualify(String attr) { - return ServerWebExchangeUtils.class.getName() + "." + attr; - } - - public static boolean setResponseStatus(ServerWebExchange exchange, HttpStatus httpStatus) { - boolean response = exchange.getResponse().setStatusCode(httpStatus); - if (!response && logger.isWarnEnabled()) { - logger.warn("Unable to set status code to "+ httpStatus + ". Response already committed."); - } - return response; - } - - public static HttpStatus parse(String statusString) { - HttpStatus httpStatus; - - try { - int status = Integer.parseInt(statusString); - httpStatus = HttpStatus.valueOf(status); - } catch (NumberFormatException e) { - // try the enum string - httpStatus = HttpStatus.valueOf(statusString.toUpperCase()); - } - return httpStatus; - } -} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/SubnetUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/SubnetUtils.java deleted file mode 100644 index fc7193c3..00000000 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/SubnetUtils.java +++ /dev/null @@ -1,364 +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.support; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A class that performs some subnet calculations given a network address and a subnet mask. - * See original from commons-net org.apache.commons.net.util.SubnetUtils - * @see "http://www.faqs.org/rfcs/rfc1519.html" - */ -@SuppressWarnings("unused") -public class SubnetUtils { - - private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"; - private static final String SLASH_FORMAT = IP_ADDRESS + "/(\\d{1,3})"; - private static final Pattern addressPattern = Pattern.compile(IP_ADDRESS); - private static final Pattern cidrPattern = Pattern.compile(SLASH_FORMAT); - private static final int NBITS = 32; - - private int netmask = 0; - private int address = 0; - private int network = 0; - private int broadcast = 0; - - /** Whether the broadcast/network address are included in host count */ - private boolean inclusiveHostCount = false; - - - /** - * Constructor that takes a CIDR-notation string, e.g. "192.168.0.1/16" - * @param cidrNotation A CIDR-notation string, e.g. "192.168.0.1/16" - * @throws IllegalArgumentException if the parameter is invalid, - * i.e. does not match n.n.n.n/m where n=1-3 decimal digits, m = 1-3 decimal digits in range 1-32 - */ - public SubnetUtils(String cidrNotation) { - calculate(cidrNotation); - } - - /** - * Constructor that takes a dotted decimal address and a dotted decimal mask. - * @param address An IP address, e.g. "192.168.0.1" - * @param mask A dotted decimal netmask e.g. "255.255.0.0" - * @throws IllegalArgumentException if the address or mask is invalid, - * i.e. does not match n.n.n.n where n=1-3 decimal digits and the mask is not all zeros - */ - public SubnetUtils(String address, String mask) { - calculate(toCidrNotation(address, mask)); - } - - - /** - * Returns true if the return value of {@link SubnetInfo#getAddressCount()} - * includes the network and broadcast addresses. - * @since 2.2 - * @return true if the hostcount includes the network and broadcast addresses - */ - public boolean isInclusiveHostCount() { - return inclusiveHostCount; - } - - /** - * Set to true if you want the return value of {@link SubnetInfo#getAddressCount()} - * to include the network and broadcast addresses. - * @param inclusiveHostCount true if network and broadcast addresses are to be included - * @since 2.2 - */ - public void setInclusiveHostCount(boolean inclusiveHostCount) { - this.inclusiveHostCount = inclusiveHostCount; - } - - - - /** - * Convenience container for subnet summary information. - * - */ - public final class SubnetInfo { - /* Mask to convert unsigned int to a long (i.e. keep 32 bits) */ - private static final long UNSIGNED_INT_MASK = 0x0FFFFFFFFL; - - private SubnetInfo() {} - - private int netmask() { return netmask; } - private int network() { return network; } - private int address() { return address; } - private int broadcast() { return broadcast; } - - // long versions of the values (as unsigned int) which are more suitable for range checking - private long networkLong() { return network & UNSIGNED_INT_MASK; } - private long broadcastLong(){ return broadcast & UNSIGNED_INT_MASK; } - - private int low() { - return (isInclusiveHostCount() ? network() : - broadcastLong() - networkLong() > 1 ? network() + 1 : 0); - } - - private int high() { - return (isInclusiveHostCount() ? broadcast() : - broadcastLong() - networkLong() > 1 ? broadcast() -1 : 0); - } - - /** - * Returns true if the parameter address is in the - * range of usable endpoint addresses for this subnet. This excludes the - * network and broadcast adresses. - * @param address A dot-delimited IPv4 address, e.g. "192.168.0.1" - * @return True if in range, false otherwise - */ - public boolean isInRange(String address) { - return isInRange(toInteger(address)); - } - - /** - * - * @param address the address to check - * @return true if it is in range - * @since 3.4 (made public) - */ - public boolean isInRange(int address) { - long addLong = address & UNSIGNED_INT_MASK; - long lowLong = low() & UNSIGNED_INT_MASK; - long highLong = high() & UNSIGNED_INT_MASK; - return addLong >= lowLong && addLong <= highLong; - } - - public String getBroadcastAddress() { - return format(toArray(broadcast())); - } - - public String getNetworkAddress() { - return format(toArray(network())); - } - - public String getNetmask() { - return format(toArray(netmask())); - } - - public String getAddress() { - return format(toArray(address())); - } - - /** - * Return the low address as a dotted IP address. - * Will be zero for CIDR/31 and CIDR/32 if the inclusive flag is false. - * - * @return the IP address in dotted format, may be "0.0.0.0" if there is no valid address - */ - public String getLowAddress() { - return format(toArray(low())); - } - - /** - * Return the high address as a dotted IP address. - * Will be zero for CIDR/31 and CIDR/32 if the inclusive flag is false. - * - * @return the IP address in dotted format, may be "0.0.0.0" if there is no valid address - */ - public String getHighAddress() { - return format(toArray(high())); - } - - /** - * Get the count of available addresses. - * Will be zero for CIDR/31 and CIDR/32 if the inclusive flag is false. - * @return the count of addresses, may be zero. - * @throws RuntimeException if the correct count is greater than {@code Integer.MAX_VALUE} - * @deprecated (3.4) use {@link #getAddressCountLong()} instead - */ - @Deprecated - public int getAddressCount() { - long countLong = getAddressCountLong(); - if (countLong > Integer.MAX_VALUE) { - throw new RuntimeException("Count is larger than an integer: " + countLong); - } - // N.B. cannot be negative - return (int)countLong; - } - - /** - * Get the count of available addresses. - * Will be zero for CIDR/31 and CIDR/32 if the inclusive flag is false. - * @return the count of addresses, may be zero. - * @since 3.4 - */ - public long getAddressCountLong() { - long b = broadcastLong(); - long n = networkLong(); - long count = b - n + (isInclusiveHostCount() ? 1 : -1); - return count < 0 ? 0 : count; - } - - public int asInteger(String address) { - return toInteger(address); - } - - public String getCidrSignature() { - return toCidrNotation( - format(toArray(address())), - format(toArray(netmask())) - ); - } - - public String[] getAllAddresses() { - int ct = getAddressCount(); - String[] addresses = new String[ct]; - if (ct == 0) { - return addresses; - } - for (int add = low(), j=0; add <= high(); ++add, ++j) { - addresses[j] = format(toArray(add)); - } - return addresses; - } - - /** - * {@inheritDoc} - * @since 2.2 - */ - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(); - buf.append("CIDR Signature:\t[").append(getCidrSignature()).append("]") - .append(" Netmask: [").append(getNetmask()).append("]\n") - .append("Network:\t[").append(getNetworkAddress()).append("]\n") - .append("Broadcast:\t[").append(getBroadcastAddress()).append("]\n") - .append("First Address:\t[").append(getLowAddress()).append("]\n") - .append("Last Address:\t[").append(getHighAddress()).append("]\n") - .append("# Addresses:\t[").append(getAddressCount()).append("]\n"); - return buf.toString(); - } - } - - /** - * Return a {@link SubnetInfo} instance that contains subnet-specific statistics - * @return new instance - */ - public final SubnetInfo getInfo() { return new SubnetInfo(); } - - /* - * Initialize the internal fields from the supplied CIDR mask - */ - private void calculate(String mask) { - Matcher matcher = cidrPattern.matcher(mask); - - if (matcher.matches()) { - address = matchAddress(matcher); - - /* Create a binary netmask from the number of bits specification /x */ - int cidrPart = rangeCheck(Integer.parseInt(matcher.group(5)), 0, NBITS); - for (int j = 0; j < cidrPart; ++j) { - netmask |= (1 << 31 - j); - } - - /* Calculate base network address */ - network = (address & netmask); - - /* Calculate broadcast address */ - broadcast = network | ~(netmask); - } else { - throw new IllegalArgumentException("Could not parse [" + mask + "]"); - } - } - - /* - * Convert a dotted decimal format address to a packed integer format - */ - private int toInteger(String address) { - Matcher matcher = addressPattern.matcher(address); - if (matcher.matches()) { - return matchAddress(matcher); - } else { - throw new IllegalArgumentException("Could not parse [" + address + "]"); - } - } - - /* - * Convenience method to extract the components of a dotted decimal address and - * pack into an integer using a regex match - */ - private int matchAddress(Matcher matcher) { - int addr = 0; - for (int i = 1; i <= 4; ++i) { - int n = (rangeCheck(Integer.parseInt(matcher.group(i)), 0, 255)); - addr |= ((n & 0xff) << 8*(4-i)); - } - return addr; - } - - /* - * Convert a packed integer address into a 4-element array - */ - private int[] toArray(int val) { - int ret[] = new int[4]; - for (int j = 3; j >= 0; --j) { - ret[j] |= ((val >>> 8*(3-j)) & (0xff)); - } - return ret; - } - - /* - * Convert a 4-element array into dotted decimal format - */ - private String format(int[] octets) { - StringBuilder str = new StringBuilder(); - for (int i =0; i < octets.length; ++i){ - str.append(octets[i]); - if (i != octets.length - 1) { - str.append("."); - } - } - return str.toString(); - } - - /* - * Convenience function to check integer boundaries. - * Checks if a value x is in the range [begin,end]. - * Returns x if it is in range, throws an exception otherwise. - */ - private int rangeCheck(int value, int begin, int end) { - if (value >= begin && value <= end) { // (begin,end] - return value; - } - - throw new IllegalArgumentException("Value [" + value + "] not in range ["+begin+","+end+"]"); - } - - /* - * Count the number of 1-bits in a 32-bit integer using a divide-and-conquer strategy - * see Hacker's Delight section 5.1 - */ - int pop(int x) { - x = x - ((x >>> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >>> 2) & 0x33333333); - x = (x + (x >>> 4)) & 0x0F0F0F0F; - x = x + (x >>> 8); - x = x + (x >>> 16); - return x & 0x0000003F; - } - - /* Convert two dotted decimal addresses to a single xxx.xxx.xxx.xxx/yy format - * by counting the 1-bit population in the mask address. (It may be better to count - * NBITS-#trailing zeroes for this case) - */ - private String toCidrNotation(String addr, String mask) { - return addr + "/" + pop(toInteger(mask)); - } -} diff --git a/spring-cloud-gateway-core/src/main/resources/META-INF/scripts/request_rate_limiter.lua b/spring-cloud-gateway-core/src/main/resources/META-INF/scripts/request_rate_limiter.lua deleted file mode 100644 index bfb7ebd9..00000000 --- a/spring-cloud-gateway-core/src/main/resources/META-INF/scripts/request_rate_limiter.lua +++ /dev/null @@ -1,34 +0,0 @@ -local tokens_key = KEYS[1] -local timestamp_key = KEYS[2] ---redis.log(redis.LOG_WARNING, "tokens_key " .. tokens_key) - -local rate = tonumber(ARGV[1]) -local capacity = tonumber(ARGV[2]) -local now = tonumber(ARGV[3]) -local requested = tonumber(ARGV[4]) - -local fill_time = capacity/rate -local ttl = math.floor(fill_time*2) - -local last_tokens = tonumber(redis.call("get", tokens_key)) -if last_tokens == nil then - last_tokens = capacity -end - -local last_refreshed = tonumber(redis.call("get", timestamp_key)) -if last_refreshed == nil then - last_refreshed = 0 -end - -local delta = math.max(0, now-last_refreshed) -local filled_tokens = math.min(capacity, last_tokens+(delta*rate)) -local allowed = filled_tokens >= requested -local new_tokens = filled_tokens -if allowed then - new_tokens = filled_tokens - requested -end - -redis.call("setex", tokens_key, ttl, new_tokens) -redis.call("setex", timestamp_key, ttl, now) - -return { allowed, new_tokens } diff --git a/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 1d13cae7..00000000 --- a/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,4 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\ -org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactoryTests.java deleted file mode 100644 index 22eaa88f..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactoryTests.java +++ /dev/null @@ -1,75 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.time.Duration; -import java.util.Map; - -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.getMap; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - - -/** - * @author Spencer Gibb - * @author Biju Kunjummen - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -@ActiveProfiles(profiles = "request-header-web-filter") -public class AddRequestHeaderWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void addRequestHeaderFilterWorks() { - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.addrequestheader.org") - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - Map headers = getMap(response, "headers"); - assertThat(headers).containsEntry("X-Request-Foo", "Bar"); - }) - .expectComplete() - .verify(Duration.ofMinutes(10)); - } - - @EnableAutoConfiguration - @SpringBootConfiguration - @Import(DefaultTestConfig.class) - public static class TestConfig { } - -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactoryTests.java deleted file mode 100644 index 7a0f30c6..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactoryTests.java +++ /dev/null @@ -1,78 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.util.Map; - -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.getMap; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -@ActiveProfiles(profiles = "request-parameter-web-filter") -public class AddRequestParameterWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void addRequestParameterFilterWorksBlankQuery() { - testRequestParameterFilter(""); - } - - @Test - public void addRequestParameterFilterWorksNonBlankQuery() { - testRequestParameterFilter("?baz=bam"); - } - - private void testRequestParameterFilter(String query) { - Mono result = webClient.get() - .uri("/get" + query) - .header("Host", "www.addrequestparameter.org") - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - Map args = getMap(response, "args"); - assertThat(args).containsEntry("foo", "bar"); - }) - .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/filter/factory/HystrixWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactoryTests.java deleted file mode 100644 index 57568390..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactoryTests.java +++ /dev/null @@ -1,81 +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.filter.factory; - -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.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 HystrixWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void hystrixFilterWorks() { - Mono result = webClient.get() - .uri("/get") - .header("Host", "www.hystrixsuccess.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) - .isEqualTo("hystrix_success_test"); - }) - .expectComplete() - .verify(DURATION); - } - - @Test - public void hystrixFilterTimesout() { - Mono result = webClient.get() - .uri("/delay/3") - .header("Host", "www.hystrixfailure.org") - .exchange(); - - StepVerifier.create(result) - .expectError() //TODO: can we get more specific as to the error? - .verify(); - } - - @EnableAutoConfiguration - @SpringBootConfiguration - @Import(DefaultTestConfig.class) - public static class TestConfig { } - -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactoryTests.java deleted file mode 100644 index 2ce638f0..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactoryTests.java +++ /dev/null @@ -1,69 +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.filter.factory; - -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.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 RedirectToWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void redirectToFilterWorks() { - Mono result = webClient.get() - .uri("/") - .header("Host", "www.redirectto.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.FOUND); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(HttpHeaders.LOCATION)) - .isEqualTo("http://example.org"); - }) - .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/filter/factory/RemoveNonProxyHeadersWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactoryTests.java deleted file mode 100644 index 960f2479..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactoryTests.java +++ /dev/null @@ -1,75 +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.filter.factory; - -import java.util.Map; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; - -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.filter.factory.RemoveNonProxyHeadersWebFilterFactory.DEFAULT_HEADERS_TO_REMOVE; -import static org.springframework.cloud.gateway.test.TestUtils.getMap; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -//TODO: why does this break other tests if not in a profile? -@ActiveProfiles("removenonproxyheaders") -@DirtiesContext -public class RemoveNonProxyHeadersWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void removeNonProxyHeadersFilterWorks() { - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.removenonproxyheaders.org") - .header("Proxy-Authorization", "myauth") - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - Map headers = getMap(response, "headers"); - //FIXME for (String header : DEFAULT_HEADERS_TO_REMOVE) { - assertThat(headers).doesNotContainKey("Proxy-Authorization"); - // } - }) - .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/filter/factory/RemoveRequestHeaderWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactoryTests.java deleted file mode 100644 index 083f3141..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactoryTests.java +++ /dev/null @@ -1,69 +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.filter.factory; - -import java.util.Map; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -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.getMap; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -public class RemoveRequestHeaderWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void removeRequestHeaderFilterWorks() { - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.removerequestheader.org") - .header("X-Request-Foo", "Bar") - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - Map headers = getMap(response, "headers"); - assertThat(headers).doesNotContainKey("X-Request-Foo"); - }) - .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/filter/factory/RemoveResponseHeaderWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactoryTests.java deleted file mode 100644 index 8f5a5dd4..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactoryTests.java +++ /dev/null @@ -1,63 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.http.HttpHeaders; -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 reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -public class RemoveResponseHeaderWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void removeResponseHeaderFilterWorks() { - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.removereresponseheader.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders).doesNotContainKey("X-Request-Foo"); - }) - .expectComplete() - .verify(DURATION); - } - - @EnableAutoConfiguration - @SpringBootConfiguration - public static class TestConfig { } - -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestRateLimiterWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestRateLimiterWebFilterFactoryTests.java deleted file mode 100644 index 53b7abdf..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestRateLimiterWebFilterFactoryTests.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.springframework.cloud.gateway.filter.factory; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; -import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter; -import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter.Response; -import org.springframework.cloud.gateway.test.BaseWebClientTests; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.http.HttpStatus; -import org.springframework.mock.http.server.reactive.MockServerHttpRequest; -import org.springframework.mock.http.server.reactive.MockServerWebExchange; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.tuple.Tuple; -import org.springframework.web.server.WebFilterChain; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; -import static org.springframework.cloud.gateway.filter.factory.RequestRateLimiterWebFilterFactory.BURST_CAPACITY_KEY; -import static org.springframework.cloud.gateway.filter.factory.RequestRateLimiterWebFilterFactory.KEY_RESOLVER_NAME_KEY; -import static org.springframework.cloud.gateway.filter.factory.RequestRateLimiterWebFilterFactory.REPLENISH_RATE_KEY; -import static org.springframework.tuple.TupleBuilder.tuple; - -import reactor.core.publisher.Mono; - -/** - * see https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d#file-1-check_request_rate_limiter-rb-L36-L62 - * @author Spencer Gibb - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -public class RequestRateLimiterWebFilterFactoryTests extends BaseWebClientTests { - - @Autowired - private RequestRateLimiterWebFilterFactory filterFactory; - - @MockBean - private RateLimiter rateLimiter; - - @MockBean - private WebFilterChain filterChain; - - @Test - public void allowedWorks() throws Exception { - assertFilterFactory("resolver1", "allowedkey", true, HttpStatus.OK); - } - - @Test - public void notAllowedWorks() throws Exception { - assertFilterFactory("resolver2", "notallowedkey", false, HttpStatus.TOO_MANY_REQUESTS); - } - - private void assertFilterFactory(String keyResolverName, String key, boolean allowed, HttpStatus expectedStatus) { - int replenishRate = 10; - int burstCapacity = 2 * replenishRate; - Tuple args = tuple().of(REPLENISH_RATE_KEY, replenishRate, - BURST_CAPACITY_KEY, burstCapacity, - KEY_RESOLVER_NAME_KEY, keyResolverName); - - when(rateLimiter.isAllowed(key, replenishRate, burstCapacity)) - .thenReturn(new Response(allowed, 1)); - - - MockServerHttpRequest request = MockServerHttpRequest.get("/").build(); - MockServerWebExchange exchange = new MockServerWebExchange(request); - exchange.getResponse().setStatusCode(HttpStatus.OK); - - when(this.filterChain.filter(exchange)).thenReturn(Mono.empty()); - - Mono response = filterFactory.apply(args).filter(exchange, this.filterChain); - response.subscribe(aVoid -> { - assertThat(exchange.getResponse().getStatusCode()).isEqualTo(expectedStatus); - }); - - } - - @EnableAutoConfiguration - @SpringBootConfiguration - @Import(BaseWebClientTests.DefaultTestConfig.class) - public static class TestConfig { - @Bean - KeyResolver resolver1() { - return exchange -> Mono.just("allowedkey"); - } - - @Bean - KeyResolver resolver2() { - return exchange -> Mono.just("notallowedkey"); - } - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryIntegrationTests.java deleted file mode 100644 index beff82bf..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryIntegrationTests.java +++ /dev/null @@ -1,64 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -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.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 RewritePathWebFilterFactoryIntegrationTests extends BaseWebClientTests { - - @Test - public void rewritePathFilterWorks() { - Mono result = webClient.get() - .uri("/foo/get") - .header("Host", "www.baz.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - }) - .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/filter/factory/RewritePathWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryTests.java deleted file mode 100644 index fd64e9ea..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryTests.java +++ /dev/null @@ -1,72 +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.filter.factory; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.springframework.mock.http.server.reactive.MockServerHttpRequest; -import org.springframework.mock.http.server.reactive.MockServerWebExchange; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REGEXP_KEY; -import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REPLACEMENT_KEY; -import static org.springframework.tuple.TupleBuilder.tuple; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class RewritePathWebFilterFactoryTests { - - @Test - public void rewritePathFilterWorks() { - testRewriteFilter("/foo", "/baz", "/foo/bar", "/baz/bar"); - } - - @Test - public void rewritePathFilterWithNamedGroupWorks() { - testRewriteFilter("/foo/(?\\d.*)", "/bar/baz/$\\{id}", "/foo/123", "/bar/baz/123"); - } - - private void testRewriteFilter(String regex, String replacement, String actualPath, String expectedPath) { - WebFilter filter = new RewritePathWebFilterFactory().apply(tuple().of(REGEXP_KEY, regex, REPLACEMENT_KEY, replacement)); - - MockServerHttpRequest request = MockServerHttpRequest - .get("http://localhost"+ actualPath) - .build(); - - ServerWebExchange exchange = new MockServerWebExchange(request); - - WebFilterChain filterChain = mock(WebFilterChain.class); - - ArgumentCaptor captor = ArgumentCaptor.forClass(ServerWebExchange.class); - when(filterChain.filter(captor.capture())).thenReturn(Mono.empty()); - - filter.filter(exchange, filterChain); - - ServerWebExchange webExchange = captor.getValue(); - - Assertions.assertThat(webExchange.getRequest().getURI().getPath()).isEqualTo(expectedPath); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactoryTests.java deleted file mode 100644 index 560e4198..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactoryTests.java +++ /dev/null @@ -1,85 +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.filter.factory; - -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.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.filter.factory.SecureHeadersWebFilterFactory.CONTENT_SECURITY_POLICY_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.REFERRER_POLICY_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.STRICT_TRANSPORT_SECURITY_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.X_CONTENT_TYPE_OPTIONS_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.X_DOWNLOAD_OPTIONS_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.X_FRAME_OPTIONS_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER; -import static org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactory.X_XSS_PROTECTION_HEADER; -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 SecureHeadersWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void secureHeadersFilterWorks() { - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.secureheaders.org") - .exchange(); - - SecureHeadersProperties defaults = new SecureHeadersProperties(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(X_XSS_PROTECTION_HEADER)).isEqualTo(defaults.getXssProtectionHeader()); - assertThat(httpHeaders.getFirst(STRICT_TRANSPORT_SECURITY_HEADER)).isEqualTo(defaults.getStrictTransportSecurity()); - assertThat(httpHeaders.getFirst(X_FRAME_OPTIONS_HEADER)).isEqualTo(defaults.getFrameOptions()); - assertThat(httpHeaders.getFirst(X_CONTENT_TYPE_OPTIONS_HEADER)).isEqualTo(defaults.getContentTypeOptions()); - assertThat(httpHeaders.getFirst(REFERRER_POLICY_HEADER)).isEqualTo(defaults.getReferrerPolicy()); - assertThat(httpHeaders.getFirst(CONTENT_SECURITY_POLICY_HEADER)).isEqualTo(defaults.getContentSecurityPolicy()); - assertThat(httpHeaders.getFirst(X_DOWNLOAD_OPTIONS_HEADER)).isEqualTo(defaults.getDownloadOptions()); - assertThat(httpHeaders.getFirst(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)).isEqualTo(defaults.getPermittedCrossDomainPolicies()); - }) - .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/filter/factory/SetPathWebFilterFactoryIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactoryIntegrationTests.java deleted file mode 100644 index d593e262..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactoryIntegrationTests.java +++ /dev/null @@ -1,64 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -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.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 SetPathWebFilterFactoryIntegrationTests extends BaseWebClientTests { - - @Test - public void setPathFilterDefaultValuesWork() { - Mono result = webClient.get() - .uri("/foo/get") - .header("Host", "www.setpath.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - }) - .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/filter/factory/SetPathWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactoryTests.java deleted file mode 100644 index 473546e0..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactoryTests.java +++ /dev/null @@ -1,78 +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.filter.factory; - -import java.util.HashMap; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.springframework.mock.http.server.reactive.MockServerHttpRequest; -import org.springframework.mock.http.server.reactive.MockServerWebExchange; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.gateway.filter.factory.SetPathWebFilterFactory.TEMPLATE_KEY; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE; -import static org.springframework.tuple.TupleBuilder.tuple; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class SetPathWebFilterFactoryTests { - - @Test - public void rewritePathFilterWorks() { - HashMap variables = new HashMap<>(); - testRewriteFilter("/baz/bar", "/foo/bar", "/baz/bar", variables); - } - - @Test - public void setPathFilterWithTemplateVarsWorks() { - HashMap variables = new HashMap<>(); - variables.put("id", "123"); - testRewriteFilter("/bar/baz/{id}", "/foo/123", "/bar/baz/123", variables); - } - - private void testRewriteFilter(String template, String actualPath, String expectedPath, HashMap variables) { - WebFilter filter = new SetPathWebFilterFactory().apply(tuple().of(TEMPLATE_KEY, template)); - - MockServerHttpRequest request = MockServerHttpRequest - .get("http://localhost"+ actualPath) - .build(); - - ServerWebExchange exchange = new MockServerWebExchange(request); - exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables); - - WebFilterChain filterChain = mock(WebFilterChain.class); - - ArgumentCaptor captor = ArgumentCaptor.forClass(ServerWebExchange.class); - when(filterChain.filter(captor.capture())).thenReturn(Mono.empty()); - - filter.filter(exchange, filterChain); - - ServerWebExchange webExchange = captor.getValue(); - - Assertions.assertThat(webExchange.getRequest().getURI().getPath()).isEqualTo(expectedPath); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseWebFilterFactoryTests.java deleted file mode 100644 index 0e32895f..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseWebFilterFactoryTests.java +++ /dev/null @@ -1,66 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -import org.springframework.http.HttpHeaders; -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 reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -public class SetResponseWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void setResponseHeaderFilterWorks() { - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.setreresponseheader.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders).containsKey("X-Request-Foo"); - assertThat(httpHeaders.get("X-Request-Foo")).containsExactly("Bar"); - }) - .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/filter/factory/SetStatusWebFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactoryTests.java deleted file mode 100644 index 3a0c959d..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactoryTests.java +++ /dev/null @@ -1,73 +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.filter.factory; - -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.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -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.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 SetStatusWebFilterFactoryTests extends BaseWebClientTests { - - @Test - public void setStatusIntWorks() { - setStatusStringTest("www.setstatusint.org", HttpStatus.UNAUTHORIZED); - } - - @Test - public void setStatusStringWorks() { - setStatusStringTest("www.setstatusstring.org", HttpStatus.BAD_REQUEST); - } - - private void setStatusStringTest(String host, HttpStatus status) { - Mono result = webClient.get() - .uri("/headers") - .header("Host", host) - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, status); - }) - .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/filter/ratelimit/RedisRateLimiterTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/ratelimit/RedisRateLimiterTests.java deleted file mode 100644 index 22d758f4..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/ratelimit/RedisRateLimiterTests.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.springframework.cloud.gateway.filter.ratelimit; - -import java.util.UUID; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter.Response; -import org.springframework.cloud.gateway.test.BaseWebClientTests; -import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -/** - * see https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d#file-1-check_request_rate_limiter-rb-L36-L62 - * @author Spencer Gibb - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -public class RedisRateLimiterTests extends BaseWebClientTests { - - @Autowired - private RedisRateLimiter rateLimiter; - - @Test - public void requestRateLimiterWebFilterFactoryWorks() throws Exception { - String id = UUID.randomUUID().toString(); - - int replenishRate = 10; - int burstCapacity = 2 * replenishRate; - - // Bursts work - for (int i = 0; i < burstCapacity; i++) { - Response response = rateLimiter.isAllowed(id, replenishRate, burstCapacity); - assertThat(response.isAllowed()).as("Burst # %s is allowed", i).isTrue(); - } - - Response response = rateLimiter.isAllowed(id, replenishRate, burstCapacity); - if (response.isAllowed()) { //TODO: sometimes there is an off by one error - response = rateLimiter.isAllowed(id, replenishRate, burstCapacity); - } - assertThat(response.isAllowed()).as("Burst # %s is not allowed", burstCapacity).isFalse(); - - Thread.sleep(1000); - - // # After the burst is done, check the steady state - for (int i = 0; i < replenishRate; i++) { - response = rateLimiter.isAllowed(id, replenishRate, burstCapacity); - assertThat(response.isAllowed()).as("steady state # %s is allowed", i).isTrue(); - } - - response = rateLimiter.isAllowed(id, replenishRate, burstCapacity); - assertThat(response.isAllowed()).as("steady state # %s is allowed", replenishRate).isFalse(); - } - - @EnableAutoConfiguration - @SpringBootConfiguration - @Import(BaseWebClientTests.DefaultTestConfig.class) - public static class TestConfig { - - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateFactoryTests.java deleted file mode 100644 index f1c43129..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateFactoryTests.java +++ /dev/null @@ -1,75 +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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory.DATETIME_KEY; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.getExchange; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.minusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.minusHoursMillis; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.plusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.plusHoursMillis; -import static org.springframework.tuple.TupleBuilder.tuple; - -/** - * @author Spencer Gibb - */ -public class AfterRoutePredicateFactoryTests { - - @Test - public void beforeStringWorks() { - String dateString = minusHours(1); - - final boolean result = runPredicate(dateString); - - assertThat(result).isTrue(); - } - - @Test - public void afterStringWorks() { - String dateString = plusHours(1); - - final boolean result = runPredicate(dateString); - - assertThat(result).isFalse(); - } - - @Test - public void beforeEpochWorks() { - String dateString = minusHoursMillis(1); - - final boolean result = runPredicate(dateString); - - assertThat(result).isTrue(); - } - - @Test - public void afterEpochWorks() { - String dateString = plusHoursMillis(1); - - final boolean result = runPredicate(dateString); - - assertThat(result).isFalse(); - } - - private boolean runPredicate(String dateString) { - return new AfterRoutePredicateFactory().apply(tuple().of(DATETIME_KEY, dateString)).test(getExchange()); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateFactoryTests.java deleted file mode 100644 index 1fe8612a..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BeforeRoutePredicateFactoryTests.java +++ /dev/null @@ -1,75 +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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory.DATETIME_KEY; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.getExchange; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.minusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.minusHoursMillis; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.plusHours; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests.plusHoursMillis; -import static org.springframework.tuple.TupleBuilder.tuple; - -/** - * @author Spencer Gibb - */ -public class BeforeRoutePredicateFactoryTests { - - @Test - public void beforeStringWorks() { - String dateString = minusHours(1); - - boolean result = runPredicate(dateString); - - assertThat(result).isFalse(); - } - - @Test - public void afterStringWorks() { - String dateString = plusHours(1); - - boolean result = runPredicate(dateString); - - assertThat(result).isTrue(); - } - - @Test - public void beforeEpochWorks() { - String dateString = minusHoursMillis(1); - - final boolean result = runPredicate(dateString); - - assertThat(result).isFalse(); - } - - @Test - public void afterEpochWorks() { - String dateString = plusHoursMillis(1); - - final boolean result = runPredicate(dateString); - - assertThat(result).isTrue(); - } - - private boolean runPredicate(String dateString) { - return new BeforeRoutePredicateFactory().apply(tuple().of(DATETIME_KEY, dateString)).test(getExchange()); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateFactoryTests.java deleted file mode 100644 index add92802..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/BetweenRoutePredicateFactoryTests.java +++ /dev/null @@ -1,125 +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.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -import org.junit.Test; -import org.springframework.mock.http.server.reactive.MockServerHttpRequest; -import org.springframework.mock.http.server.reactive.MockServerWebExchange; -import org.springframework.web.server.ServerWebExchange; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory.DATETIME1_KEY; -import static org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory.DATETIME2_KEY; -import static org.springframework.tuple.TupleBuilder.tuple; - -/** - * @author Spencer Gibb - */ -public class BetweenRoutePredicateFactoryTests { - - @Test - public void beforeStringWorks() { - String dateString1 = plusHours(1); - String dateString2 = plusHours(2); - - final boolean result = runPredicate(dateString1, dateString2); - - assertThat(result).as("Now is not before %s", dateString1).isFalse(); - } - - @Test - public void betweenStringWorks() { - String dateString1 = minusHours(1); - String dateString2 = plusHours(1); - - final boolean result = runPredicate(dateString1, dateString2); - - assertThat(result).as("Now is not between %s and %s", dateString1, dateString2).isTrue(); - } - - @Test - public void afterStringWorks() { - String dateString1 = minusHours(2); - String dateString2 = minusHours(1); - - final boolean result = runPredicate(dateString1, dateString2); - - assertThat(result).as("Now is not after %s", dateString2).isFalse(); - } - - @Test - public void beforeEpochWorks() { - String dateString1 = plusHoursMillis(1); - String dateString2 = plusHoursMillis(2); - - final boolean result = runPredicate(dateString1, dateString2); - - assertThat(result).as("Now is not before %s", dateString1).isFalse(); - } - - @Test - public void betweenEpochWorks() { - String dateString1 = minusHoursMillis(1); - String dateString2 = plusHoursMillis(1); - - final boolean result = runPredicate(dateString1, dateString2); - - assertThat(result).as("Now is not between %s and %s", dateString1, dateString2).isTrue(); - } - - @Test - public void afterEpochWorks() { - String dateString1 = minusHoursMillis(2); - String dateString2 = minusHoursMillis(1); - - final boolean result = runPredicate(dateString1, dateString2); - - assertThat(result).as("Now is not after %s", dateString1).isFalse(); - } - - boolean runPredicate(String dateString1, String dateString2) { - return new BetweenRoutePredicateFactory().apply(tuple() - .of(DATETIME1_KEY, dateString1, DATETIME2_KEY, dateString2)).test(getExchange()); - } - - static String minusHoursMillis(int hours) { - final int millis = hours * 1000 * 60 * 60; - return String.valueOf(System.currentTimeMillis() - millis); - } - - static String plusHoursMillis(int hours) { - final int millis = hours * 1000 * 60 * 60; - return String.valueOf(System.currentTimeMillis() + millis); - } - - static String minusHours(int hours) { - return ZonedDateTime.now().minusHours(hours).format(DateTimeFormatter.ISO_ZONED_DATE_TIME); - } - - static String plusHours(int hours) { - return ZonedDateTime.now().plusHours(hours).format(DateTimeFormatter.ISO_ZONED_DATE_TIME); - } - - static ServerWebExchange getExchange() { - MockServerHttpRequest request = MockServerHttpRequest.get("http://example.com").build(); - return new MockServerWebExchange(request); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java deleted file mode 100644 index 99298956..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HostRoutePredicateFactoryTests.java +++ /dev/null @@ -1,72 +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 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.RoutePredicateHandlerMapping; -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 HostRoutePredicateFactoryTests extends BaseWebClientTests { - - @Test - public void hostRouteWorks() { - Mono result = webClient.get() - .uri("/get") - .header("Host", "www.example.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) - .isEqualTo(RoutePredicateHandlerMapping.class.getSimpleName()); - assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) - .isEqualTo("host_example_to_httpbin"); - }) - .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/MethodRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicateFactoryTests.java deleted file mode 100644 index b814ca0a..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/MethodRoutePredicateFactoryTests.java +++ /dev/null @@ -1,72 +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 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.RoutePredicateHandlerMapping; -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 MethodRoutePredicateFactoryTests 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(RoutePredicateHandlerMapping.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/PathRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactoryTests.java deleted file mode 100644 index 0945ca61..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactoryTests.java +++ /dev/null @@ -1,71 +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 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.RoutePredicateHandlerMapping; -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 PathRoutePredicateFactoryTests extends BaseWebClientTests { - - @Test - public void pathRouteWorks() { - Mono result = webClient.get() - .uri("/get") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) - .isEqualTo(RoutePredicateHandlerMapping.class.getSimpleName()); - assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) - .isEqualTo("default_path_to_httpbin"); - }) - .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/RoutePredicatesTest.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicatesTest.java deleted file mode 100644 index 742d5b2e..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/RoutePredicatesTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 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.springframework.http.HttpMethod; -import org.springframework.mock.http.server.reactive.MockServerHttpRequest; -import org.springframework.web.server.ServerWebExchange; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.handler.predicate.RoutePredicates.host; -import static org.springframework.cloud.gateway.handler.predicate.RoutePredicates.method; -import static org.springframework.cloud.gateway.handler.predicate.RoutePredicates.path; - -/** - * @author Biju Kunjummen - */ -public class RoutePredicatesTest { - - @Test - public void testHostPredicates() { - assertThat(host("**").test(mockHostExchange("test.abc.com"))).isTrue(); - assertThat(host("**.abc.**").test(mockHostExchange("test.abc.com"))).isTrue(); - assertThat(host("**.co?").test(mockHostExchange("test.abc.com"))).isTrue(); - assertThat(host("**.co").test(mockHostExchange("test.abc.com"))).isFalse(); - - } - - @Test - public void testPathPredicates() { - assertThat(path("/**").test(mockPathExchange("/path1/path2"))).isTrue(); - assertThat(path("/path1/*").test(mockPathExchange("/path1/path2"))).isTrue(); - assertThat(path("/path1/path?").test(mockPathExchange("/path1/path2"))).isTrue(); - } - - @Test - public void testMethodPredicates() { - assertThat(method("GET").test(mockMethodExchange("GET"))).isTrue(); - assertThat(method("POST").test(mockMethodExchange("POST"))).isTrue(); - assertThat(method("PUT").test(mockMethodExchange("PUT"))).isTrue(); - } - - private ServerWebExchange mockHostExchange(String host) { - MockServerHttpRequest mockRequest = MockServerHttpRequest.get("/") - .header("Host", host).build(); - return mockRequest.toExchange(); - } - - private ServerWebExchange mockPathExchange(String path) { - MockServerHttpRequest mockRequest = MockServerHttpRequest.get(path).build(); - return mockRequest.toExchange(); - } - - private ServerWebExchange mockMethodExchange(String method) { - MockServerHttpRequest mockRequest = MockServerHttpRequest - .method(HttpMethod.resolve(method), "/").build(); - return mockRequest.toExchange(); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java deleted file mode 100644 index 16ef7002..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java +++ /dev/null @@ -1,99 +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.test; - -import org.junit.ClassRule; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; -import org.junit.runners.model.Statement; -import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.AddRequestParameterWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.HystrixWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.RedirectToWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.RemoveNonProxyHeadersWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactoryIntegrationTests; -import org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.SecureHeadersWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.SetPathWebFilterFactoryIntegrationTests; -import org.springframework.cloud.gateway.filter.factory.SetPathWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.SetResponseWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.factory.SetStatusWebFilterFactoryTests; -import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiterTests; -import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactoryTests; -import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactoryTests; -import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactoryTests; -import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactoryTests; -import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactoryTests; -import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactoryTests; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assume.assumeThat; - -/** - * To run this suite in an IDE, set env var GATEWAY_ADHOC_ENABLED=true in test runner. - * @author Spencer Gibb - */ -@RunWith(Suite.class) -@SuiteClasses({GatewayIntegrationTests.class, - FormIntegrationTests.class, - PostTests.class, - RedisRateLimiterTests.class, - // route filter tests - AddRequestHeaderWebFilterFactoryTests.class, - AddRequestParameterWebFilterFactoryTests.class, - HystrixWebFilterFactoryTests.class, - RedirectToWebFilterFactoryTests.class, - RemoveNonProxyHeadersWebFilterFactoryTests.class, - RemoveRequestHeaderWebFilterFactoryTests.class, - RewritePathWebFilterFactoryIntegrationTests.class, - SecureHeadersWebFilterFactoryTests.class, - SetPathWebFilterFactoryIntegrationTests.class, - SetPathWebFilterFactoryTests.class, - SetResponseWebFilterFactoryTests.class, - SetStatusWebFilterFactoryTests.class, - RewritePathWebFilterFactoryTests.class, - // RoutePredicateFactory tests - AfterRoutePredicateFactoryTests.class, - BeforeRoutePredicateFactoryTests.class, - BetweenRoutePredicateFactoryTests.class, - HostRoutePredicateFactoryTests.class, - MethodRoutePredicateFactoryTests.class, - PathRoutePredicateFactoryTests.class, -}) -public class AdhocTestSuite { - - @ClassRule - public static AdhocEnabled adhocEnabled = new AdhocEnabled(); - - static class AdhocEnabled implements TestRule { - - @Override - public Statement apply(Statement base, Description description) { - assumeThat("Adhoc Tests ignored", - System.getenv("GATEWAY_ADHOC_ENABLED"), - is(equalTo("true"))); - - return base; - } - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/BaseWebClientTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/BaseWebClientTests.java deleted file mode 100644 index 1d1dda35..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/BaseWebClientTests.java +++ /dev/null @@ -1,199 +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.test; - -import java.io.IOException; -import java.time.Duration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.cloud.gateway.EnableGateway; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.cloud.gateway.route.Route; -import org.springframework.cloud.netflix.ribbon.RibbonClient; -import org.springframework.cloud.netflix.ribbon.RibbonClients; -import org.springframework.cloud.netflix.ribbon.StaticServerList; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.codec.multipart.Part; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.server.ServerWebExchange; - -import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.ServerList; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; - -import reactor.core.publisher.Mono; - -/** - * @author Spencer Gibb - */ -public class BaseWebClientTests { - - protected static final String HANDLER_MAPPER_HEADER = "X-Gateway-Handler-Mapper-Class"; - protected static final String ROUTE_ID_HEADER = "X-Gateway-RouteDefinition-Id"; - protected static final Duration DURATION = Duration.ofSeconds(5); - - @LocalServerPort - protected int port = 0; - - protected WebClient webClient; - protected String baseUri; - - @Before - public void setup() { - //TODO: how to set new ReactorClientHttpConnector() - baseUri = "http://localhost:" + port; - this.webClient = WebClient.create(baseUri); - } - - @RestController - @RequestMapping("/httpbin") - @Configuration - @RibbonClients({ - @RibbonClient(name = "testservice", configuration = TestRibbonConfig.class), - @RibbonClient(name = "myservice", configuration = TestRibbonConfig.class) - }) - @EnableGateway - protected static class DefaultTestConfig { - - private static final Log log = LogFactory.getLog(DefaultTestConfig.class); - - @RequestMapping("/") - public String home(ServerWebExchange exchange) { - return "httpbin compatible home"; - } - - @RequestMapping("/headers") - public Map headers(ServerWebExchange exchange) { - HashMap map = new HashMap<>(); - addHeaders(exchange, map); - return map; - } - - private void addHeaders(ServerWebExchange exchange, HashMap map) { - HashMap headers = new HashMap<>(); - exchange.getRequest().getHeaders().forEach((name, values) -> { - headers.put(name, values.get(0)); - }); - - map.put("headers", headers); - } - - @RequestMapping("/delay/{sec}") - public Map get(ServerWebExchange exchange, @PathVariable int sec) throws InterruptedException { - int delay = Math.min(sec, 10); - Thread.sleep(delay * 1000); - return get(exchange); - } - - @RequestMapping("/get") - public Map get(ServerWebExchange exchange) { - HashMap map = new HashMap<>(); - addHeaders(exchange, map); - HashMap params = new HashMap<>(); - exchange.getRequest().getQueryParams().forEach((name, values) -> { - params.put(name, values.get(0)); - - }); - map.put("args", params); - return map; - } - - @RequestMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public Mono> postFormData(//ServerWebExchange exchange, - @RequestParam Map parts - /*@RequestBody(required = false) String body*/) { - HashMap ret = new HashMap<>(); - // HashMap files = parseMultipart(exchange, null); - - // ret.put("files", files); - return Mono.just(ret); - } - - @RequestMapping(path = "/post", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public Mono> postUrlEncoded(ServerWebExchange exchange) throws IOException { - return post(exchange, null); - } - - @RequestMapping("/post") - public Mono> post(ServerWebExchange exchange, - @RequestBody(required = false) String body) throws IOException { - HashMap ret = new HashMap<>(); - ret.put("data", body); - HashMap form = new HashMap<>(); - ret.put("form", form); - - return exchange.getFormData().flatMap(map -> { - for (Map.Entry> entry: map.entrySet()) { - for (String value : entry.getValue()) { - form.put(entry.getKey(), value); - } - } - return Mono.just(ret); - }); - } - - @RequestMapping("/status/{status}") - public ResponseEntity status(@PathVariable int status) { - return ResponseEntity.status(status).body("Failed with "+status); - } - - @Bean - @Order(500) - public GlobalFilter modifyResponseFilter() { - return (exchange, chain) -> { - log.info("modifyResponseFilter start"); - String value = (String) exchange.getAttribute(GATEWAY_HANDLER_MAPPER_ATTR).orElse("N/A"); - exchange.getResponse().getHeaders().add(HANDLER_MAPPER_HEADER, value); - Route route = (Route) exchange.getAttribute(GATEWAY_ROUTE_ATTR).orElse(null); - if (route != null) { - exchange.getResponse().getHeaders().add(ROUTE_ID_HEADER, route.getId()); - } - return chain.filter(exchange); - }; - } - } - - protected static class TestRibbonConfig { - - @LocalServerPort - protected int port = 0; - - @Bean - public ServerList ribbonServerList() { - return new StaticServerList<>(new Server("localhost", this.port)); - } - } - -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java deleted file mode 100644 index cee50250..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java +++ /dev/null @@ -1,114 +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.test; - -import java.nio.charset.Charset; -import java.util.Map; - -import org.junit.Ignore; -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.context.annotation.Import; -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.BodyInserters; - -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.getMap; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -@SuppressWarnings("unchecked") -public class FormIntegrationTests extends BaseWebClientTests { - - @Test - public void formUrlencodedWorks() { - LinkedMultiValueMap formData = new LinkedMultiValueMap<>(); - formData.add("foo", "bar"); - formData.add("baz", "bam"); - - MediaType contentType = new MediaType(MediaType.APPLICATION_FORM_URLENCODED, Charset.forName("UTF-8")); - Mono result = webClient.post() - .uri("/post") - .contentType(contentType) - .body(BodyInserters.fromFormData(formData)) - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith(map -> { - Map form = getMap(map, "form"); - assertThat(form).containsEntry("foo", "bar"); - assertThat(form).containsEntry("baz", "bam"); - }) - .expectComplete() - .verify(DURATION); - } - - @Test - @Ignore //FIXME: java.lang.IllegalStateException: Only one connection receive subscriber allowed. - public void multipartFormDataWorks() { - ClassPathResource img = new ClassPathResource("1x1.png"); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.IMAGE_PNG); - - HttpEntity entity = new HttpEntity<>(img, headers); - - MultiValueMap parts = new LinkedMultiValueMap<>(); - parts.add("imgpart", entity); - - Mono result = webClient.post() - .uri("/post") - .contentType(MediaType.MULTIPART_FORM_DATA) - .body(BodyInserters.fromMultipartData(parts)) - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith(map -> { - Map files = getMap(map, "files"); - assertThat(files).containsKey("file"); - String file = (String) files.get("file"); - assertThat(file).startsWith("data:").contains(";base64,"); - }) - .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/test/GatewayIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java deleted file mode 100644 index a5e10fc0..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java +++ /dev/null @@ -1,171 +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.test; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -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.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.server.ServerWebExchange; - -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 static org.springframework.cloud.gateway.test.TestUtils.getMap; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -@SuppressWarnings("unchecked") -public class GatewayIntegrationTests extends BaseWebClientTests { - - @Autowired - private GatewayProperties properties; - - @Test - public void complexContentTypeWorks() { - Mono result = webClient.post() - .uri("/headers") - .contentType(MediaType.APPLICATION_JSON_UTF8) - .syncBody("testdata") - .header("Host", "www.complexcontenttype.org") - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - Map headers = getMap(response, "headers"); - assertThat(headers).containsEntry(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE); - }) - .expectComplete() - .verify(DURATION); - } - - @Test - public void compositeRouteWorks() { - Mono result = webClient.get() - .uri("/headers?foo=bar&baz") - .header("Host", "www.foo.org") - .header("X-Request-Id", "123") - .cookie("chocolate", "chip") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER)) - .isEqualTo(RoutePredicateHandlerMapping.class.getSimpleName()); - assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) - .isEqualTo("host_foo_path_headers_to_httpbin"); - assertThat(httpHeaders.getFirst("X-Response-Foo")) - .isEqualTo("Bar"); - }) - .expectComplete() - .verify(); - } - - @Test - public void defaultFiltersWorks() { - assertThat(this.properties.getDefaultFilters()).isNotEmpty(); - - Mono result = webClient.get() - .uri("/headers") - .header("Host", "www.addresponseheader.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst("X-Response-Default-Foo")) - .isEqualTo("Default-Bar"); - assertThat(httpHeaders.get("X-Response-Default-Foo")).hasSize(1); - }) - .expectComplete() - .verify(DURATION); - } - - @Test - public void loadBalancerFilterWorks() { - Mono result = webClient.get() - .uri("/get") - .header("Host", "www.loadbalancerclient.org") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.OK); - HttpHeaders httpHeaders = response.headers().asHttpHeaders(); - assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER)) - .isEqualTo("load_balancer_client_test"); - }) - .expectComplete() - .verify(DURATION); - } - - @EnableAutoConfiguration - @SpringBootConfiguration - @Import(DefaultTestConfig.class) - public static class TestConfig { - - private static final Log log = LogFactory.getLog(TestConfig.class); - - @Bean - @Order(-1) - public GlobalFilter postFilter() { - return (exchange, chain) -> { - log.info("postFilter start"); - return chain.filter(exchange).then(postFilterWork(exchange)); - }; - } - - private static Mono postFilterWork(ServerWebExchange exchange) { - log.info("postFilterWork"); - exchange.getResponse().getHeaders().add("X-Post-Header", "AddedAfterRoute"); - return Mono.empty(); - } - - } - -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java deleted file mode 100644 index 67e6835a..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/GatewayTestApplication.java +++ /dev/null @@ -1,55 +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.test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.gateway.EnableGateway; -import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -@EnableGateway -@SpringBootConfiguration -@EnableAutoConfiguration -public class GatewayTestApplication { - - /* - TO test run `spring cloud configserver eureka`, - then run this app with `--spring.profiles.active=discovery` - should be able to hit http://localhost:8008/configserver/foo/default a normal configserver api - */ - @Configuration - @EnableDiscoveryClient - @Profile("discovery") - protected static class GatewayDiscoveryConfiguration { - - @Bean - public DiscoveryClientRouteDefinitionLocator discoveryClientRouteLocator(DiscoveryClient discoveryClient) { - return new DiscoveryClientRouteDefinitionLocator(discoveryClient); - } - } - - public static void main(String[] args) { - SpringApplication.run(GatewayTestApplication.class, args); - } -} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/HttpStatusTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/HttpStatusTests.java deleted file mode 100644 index 93e8aa14..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/HttpStatusTests.java +++ /dev/null @@ -1,63 +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.test; - -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.context.annotation.Import; -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.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 -@SuppressWarnings("unchecked") -public class HttpStatusTests extends BaseWebClientTests { - - @Test - public void notFoundResponseWorks() { - Mono result = webClient.get() - .uri("/status/404") - .exchange(); - - StepVerifier.create(result) - .consumeNextWith( - response -> { - assertStatus(response, HttpStatus.NOT_FOUND); - }) - .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/test/PostTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/PostTests.java deleted file mode 100644 index 15b4d35a..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/PostTests.java +++ /dev/null @@ -1,65 +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.test; - -import java.util.Map; - -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.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; -import static org.springframework.web.reactive.function.BodyExtractors.toMono; - -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT) -@DirtiesContext -@SuppressWarnings("unchecked") -//TODO: why does this have to be in a separate test? -public class PostTests extends BaseWebClientTests { - - @Test - public void postWorks() { - Mono result = webClient.post() - .uri("/post") - .header("Host", "www.example.org") - .syncBody("testdata") - .exchange() - .flatMap(response -> response.body(toMono(Map.class))); - - StepVerifier.create(result) - .consumeNextWith(map -> assertThat(map).containsEntry("data", "testdata")) - .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/test/TestUtils.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/TestUtils.java deleted file mode 100644 index 3a454a73..00000000 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/TestUtils.java +++ /dev/null @@ -1,42 +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.test; - -import java.util.Map; - -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.ClientResponse; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Spencer Gibb - */ -public class TestUtils { - @SuppressWarnings("unchecked") - public static Map getMap(Map response, String key) { - assertThat(response).containsKey(key).isInstanceOf(Map.class); - return (Map) response.get(key); - } - - public static void assertStatus(ClientResponse response, HttpStatus status) { - HttpStatus statusCode = response.statusCode(); - assertThat(statusCode).isEqualTo(status); - } - -} diff --git a/spring-cloud-gateway-core/src/test/resources/1x1.png b/spring-cloud-gateway-core/src/test/resources/1x1.png deleted file mode 100644 index 134aa5b7..00000000 Binary files a/spring-cloud-gateway-core/src/test/resources/1x1.png and /dev/null differ diff --git a/spring-cloud-gateway-core/src/test/resources/application-removenonproxyheaders.yml b/spring-cloud-gateway-core/src/test/resources/application-removenonproxyheaders.yml deleted file mode 100644 index 2a9cc127..00000000 --- a/spring-cloud-gateway-core/src/test/resources/application-removenonproxyheaders.yml +++ /dev/null @@ -1,18 +0,0 @@ - -spring: - cloud: - gateway: - default-filters: - - RemoveNonProxyHeaders - - PrefixPath=/httpbin - routes: - # ===================================== - - id: remove_request_header_test -# uri: http://httpbin.org:80 - uri: lb://testservice - predicates: - - Host=**.removenonproxyheaders.org - - Path=/headers - filters: - - RemoveRequestHeader=X-Request-Foo - diff --git a/spring-cloud-gateway-core/src/test/resources/application-request-header-web-filter.yml b/spring-cloud-gateway-core/src/test/resources/application-request-header-web-filter.yml deleted file mode 100644 index e76ddf47..00000000 --- a/spring-cloud-gateway-core/src/test/resources/application-request-header-web-filter.yml +++ /dev/null @@ -1,14 +0,0 @@ -test: - hostport: httpbin.org:80 - uri: lb://testservice - -spring: - cloud: - gateway: - routes: - - id: add_request_header_test - uri: ${test.uri} - predicates: - - Path=/headers - filters: - - AddRequestHeader=X-Request-Foo, Bar diff --git a/spring-cloud-gateway-core/src/test/resources/application-request-parameter-web-filter.yml b/spring-cloud-gateway-core/src/test/resources/application-request-parameter-web-filter.yml deleted file mode 100644 index f3d3c4c0..00000000 --- a/spring-cloud-gateway-core/src/test/resources/application-request-parameter-web-filter.yml +++ /dev/null @@ -1,15 +0,0 @@ -test: - hostport: httpbin.org:80 - uri: lb://testservice - -spring: - cloud: - gateway: - routes: - - id: add_request_parameter_test - uri: ${test.uri} - predicates: - - Host=**.addrequestparameter.org - - Path=/get - filters: - - AddRequestParameter=foo, bar diff --git a/spring-cloud-gateway-core/src/test/resources/application.yml b/spring-cloud-gateway-core/src/test/resources/application.yml deleted file mode 100644 index 88f400be..00000000 --- a/spring-cloud-gateway-core/src/test/resources/application.yml +++ /dev/null @@ -1,203 +0,0 @@ -test: - hostport: httpbin.org:80 -# hostport: localhost:5000 -# uri: http://${test.hostport} - uri: lb://testservice - -spring: - cloud: - gateway: - default-filters: - - AddResponseHeader=X-Response-Default-Foo, Default-Bar - - PrefixPath=/httpbin - - # TODO: breakup configuration for individual tests (though some are reused) - routes: - # ===================================== - - host_example_to_httpbin=${test.uri}, Host=**.example.org - - # ===================================== - - id: host_foo_path_headers_to_httpbin - uri: ${test.uri} - predicates: - - Host=**.foo.org - - Path=/headers - - Method=GET - - Header=X-Request-Id, \d+ - - Query=foo, ba. - - Query=baz - - Cookie=chocolate, ch.p - - After=1900-01-20T17:42:47.789-07:00[America/Denver] - filters: - - AddResponseHeader=X-Response-Foo, Bar - - # ===================================== - - id: add_request_header_test - uri: ${test.uri} - predicates: - - Host=**.addrequestheader.org - - Path=/headers - filters: - - AddRequestHeader=X-Request-Foo, Bar - - # ===================================== - - id: add_request_parameter_test - uri: ${test.uri} - predicates: - - Host=**.addrequestparameter.org - - Path=/get - filters: - - AddRequestParameter=foo, bar - - # ===================================== - - id: add_response_header_test - uri: ${test.uri} - predicates: - - Host=**.addresponseheader.org - - Path=/headers - filters: - - AddResponseHeader=X-Request-Foo, Bar - - # ===================================== - - id: hystrix_failure_test - uri: ${test.uri} - predicates: - - Host=**.hystrixfailure.org - filters: - - Hystrix=failcmd - - # ===================================== - - id: hystrix_success_test - uri: ${test.uri} - predicates: - - Host=**.hystrixsuccess.org - filters: - - Hystrix=successcmd - - # ===================================== - - id: load_balancer_client_test - uri: lb://myservice - predicates: - - Host=**.loadbalancerclient.org - - # ===================================== - - id: method_test - uri: ${test.uri} - predicates: - - Method=GET - - Host=**.method.org - - # ===================================== - - id: redirect_to_test - uri: ${test.uri} - predicates: - - Host=**.redirectto.org - filters: - - RedirectTo=302, http://example.org - - # ===================================== - - id: remove_request_header_test - uri: ${test.uri} - predicates: - - Host=**.removerequestheader.org - - Path=/headers - filters: - - RemoveRequestHeader=X-Request-Foo - - # ===================================== - - id: remove_response_header_test - uri: ${test.uri} - predicates: - - Host=**.removereresponseheader.org - - Path=/headers - filters: - - AddResponseHeader=X-Request-Foo, Bar - - RemoveResponseHeader=X-Request-Foo - - # ===================================== - - id: secure_headers_test - uri: ${test.uri} - predicates: - - Host=**.secureheaders.org - - Path=/headers - filters: - - SecureHeaders - - # ===================================== - - id: set_path_test - uri: ${test.uri} - predicates: - - Host=**.setpath.org - - Path=/foo/{segment} - filters: - - SetPath=/{segment} - - # ===================================== - - id: set_response_header_test - uri: ${test.uri} - predicates: - - Host=**.setreresponseheader.org - - Path=/headers - filters: - - AddResponseHeader=X-Request-Foo, Bar1 - - AddResponseHeader=X-Request-Foo, Bar2 - - SetResponseHeader=X-Request-Foo, Bar - - # ===================================== - - id: set_status_int_test - uri: ${test.uri} - predicates: - - Host=**.setstatusint.org - - Path=/headers - filters: - - name: SetStatus - args: - status: 401 - - # ===================================== - - id: set_status_string_test - uri: ${test.uri} - predicates: - - Host=**.setstatusstring.org - - Path=/headers - filters: - - SetStatus=BAD_REQUEST - - # ===================================== - - id: rewrite_path_test - uri: ${test.uri} - predicates: - - Host=**.baz.org - - RemoteAddr=127.0.0.1/24 - filters: - # $\ is being used as an escape - - RewritePath=/foo/(?.*), /$\{segment} - - AddRequestHeader=X-Request-Foo, Bar - - AddRequestHeader=X-Request-Baz, Bat - - # ===================================== - - id: default_path_to_httpbin - uri: ${test.uri} - order: 10000 - predicates: - - name: Path - args: - pattern: /** - -#myservice: -# ribbon: -# NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList -# listOfServers: ${test.hostport} - -#hystrix.command.failcmd.execution.isolation.thread.timeoutInMilliseconds: 1000 - -logging: - level: - org.springframework.cloud.gateway: TRACE - org.springframework.http.server.reactive: DEBUG - org.springframework.web.reactive: DEBUG - reactor.ipc.netty: DEBUG - -management: - context-path: /admin -# port: 8081 diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 3cad857e..6c892ad4 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -5,7 +5,7 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.0.0.BUILD-SNAPSHOT + 1.3.2.RELEASE @@ -26,16 +26,6 @@ spring-cloud-gateway-mvc ${project.version} - - org.springframework.cloud - spring-cloud-gateway-core - ${project.version} - - - org.springframework.cloud - spring-cloud-starter-gateway - ${project.version} - diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index a19928f9..a214326f 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -26,34 +26,15 @@ org.springframework.boot spring-boot-starter-actuator - - org.springframework.boot - spring-boot-starter-webflux - org.springframework.cloud - spring-cloud-starter-gateway - - - org.isomorphism - token-bucket - 1.7 + spring-cloud-gateway-mvc org.springframework.boot spring-boot-starter-test test - - io.projectreactor - reactor-test - test - - - org.assertj - assertj-core - test - diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml deleted file mode 100644 index b80d1399..00000000 --- a/spring-cloud-starter-gateway/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - - org.springframework.cloud - spring-cloud-gateway - 1.0.0.BUILD-SNAPSHOT - .. - - spring-cloud-starter-gateway - spring-cloud-starter-gateway - Spring Cloud Starter - https://projects.spring.io/spring-cloud - - Pivotal Software, Inc. - https://www.spring.io - - - ${basedir}/../.. - - - - org.springframework.cloud - spring-cloud-gateway-core - - - diff --git a/spring-cloud-starter-gateway/src/main/resources/META-INF/spring.provides b/spring-cloud-starter-gateway/src/main/resources/META-INF/spring.provides deleted file mode 100644 index ff520021..00000000 --- a/spring-cloud-starter-gateway/src/main/resources/META-INF/spring.provides +++ /dev/null @@ -1 +0,0 @@ -provides: spring-cloud-gateway-core \ No newline at end of file