diff --git a/docs/src/main/asciidoc/spring-cloud-gateway.adoc b/docs/src/main/asciidoc/spring-cloud-gateway.adoc index 7c0a8117..b1c805b4 100644 --- a/docs/src/main/asciidoc/spring-cloud-gateway.adoc +++ b/docs/src/main/asciidoc/spring-cloud-gateway.adoc @@ -1400,6 +1400,38 @@ management.endpoint.gateway.enabled=true # default value management.endpoints.web.exposure.include=gateway ---- +=== Verbose Actuator Format + +A new, more verbose format has been added to Gateway. This adds more detail to each route allowing to view the predicates and filters associated to each route along with any configuration that is available. + +`/actuator/gateway/routes` +[source,json] +---- +[ + { + "predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)", + "route_id": "add_request_header_test", + "filters": [ + "[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]", + "[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]", + "[[PrefixPath prefix = '/httpbin'], order = 2]" + ], + "uri": "lb://testservice", + "order": 0 + } +] +---- + +To enable this feature, set the following property: + +.application.properties +[source,properties] +---- +spring.cloud.gateway.actuator.verbose.enabled=true +---- + +This will default to true in a future release. + === Retrieving route filters ==== Global Filters To retrieve the <> applied to all routes, make a `GET` request to `/actuator/gateway/globalfilters`. The resulting response is similar to the following: diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/AbstractGatewayControllerEndpoint.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/AbstractGatewayControllerEndpoint.java new file mode 100644 index 00000000..a56c1a0a --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/AbstractGatewayControllerEndpoint.java @@ -0,0 +1,145 @@ +/* + * Copyright 2013-2019 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 + * + * https://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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.cloud.gateway.event.RefreshRoutesEvent; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; +import org.springframework.cloud.gateway.route.RouteDefinition; +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.support.NotFoundException; +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; + +/** + * @author Spencer Gibb + */ +public class AbstractGatewayControllerEndpoint implements ApplicationEventPublisherAware { + + private static final Log log = LogFactory.getLog(GatewayControllerEndpoint.class); + + protected RouteDefinitionLocator routeDefinitionLocator; + + protected List globalFilters; + + protected List GatewayFilters; + + protected RouteDefinitionWriter routeDefinitionWriter; + + protected RouteLocator routeLocator; + + protected ApplicationEventPublisher publisher; + + public AbstractGatewayControllerEndpoint( + RouteDefinitionLocator routeDefinitionLocator, + List globalFilters, List GatewayFilters, + RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { + this.routeDefinitionLocator = routeDefinitionLocator; + this.globalFilters = globalFilters; + this.GatewayFilters = GatewayFilters; + this.routeDefinitionWriter = routeDefinitionWriter; + this.routeLocator = routeLocator; + } + + @Override + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + + // TODO: Add uncommited or new but not active routes endpoint + + @PostMapping("/refresh") + public Mono refresh() { + this.publisher.publishEvent(new RefreshRoutesEvent(this)); + return Mono.empty(); + } + + @GetMapping("/globalfilters") + public Mono> globalfilters() { + return getNamesToOrders(this.globalFilters); + } + + @GetMapping("/routefilters") + public Mono> routefilers() { + return getNamesToOrders(this.GatewayFilters); + } + + private Mono> getNamesToOrders(List list) { + return Flux.fromIterable(list).reduce(new HashMap<>(), this::putItem); + } + + private HashMap putItem(HashMap map, Object o) { + Integer order = null; + if (o instanceof Ordered) { + order = ((Ordered) o).getOrder(); + } + // filters.put(o.getClass().getName(), order); + map.put(o.toString(), order); + return map; + } + + /* + * 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}/combinedfilters") + public Mono> combinedfilters(@PathVariable String id) { + // TODO: missing global filters + return this.routeLocator.getRoutes().filter(route -> route.getId().equals(id)) + .reduce(new HashMap<>(), this::putItem); + } + +} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpoint.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpoint.java index 02a05d0e..244d976a 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpoint.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpoint.java @@ -16,188 +16,71 @@ package org.springframework.cloud.gateway.actuate; -import java.net.URI; import java.util.ArrayList; 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 reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint; -import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; import org.springframework.cloud.gateway.route.Route; -import org.springframework.cloud.gateway.route.RouteDefinition; -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.support.NotFoundException; -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; /** * @author Spencer Gibb */ @RestControllerEndpoint(id = "gateway") -public class GatewayControllerEndpoint implements ApplicationEventPublisherAware { +public class GatewayControllerEndpoint extends AbstractGatewayControllerEndpoint { - private static final Log log = LogFactory.getLog(GatewayControllerEndpoint.class); - - private RouteDefinitionLocator routeDefinitionLocator; - - private List globalFilters; - - private List GatewayFilters; - - private RouteDefinitionWriter routeDefinitionWriter; - - private RouteLocator routeLocator; - - private ApplicationEventPublisher publisher; - - public GatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, - List globalFilters, List GatewayFilters, + public GatewayControllerEndpoint(List globalFilters, + List gatewayFilters, RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { - this.routeDefinitionLocator = routeDefinitionLocator; - this.globalFilters = globalFilters; - this.GatewayFilters = GatewayFilters; - this.routeDefinitionWriter = routeDefinitionWriter; - this.routeLocator = routeLocator; - } - - @Override - public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { - this.publisher = publisher; - } - - // TODO: Add uncommited or new but not active routes endpoint - - @PostMapping("/refresh") - public Mono refresh() { - this.publisher.publishEvent(new RefreshRoutesEvent(this)); - return Mono.empty(); - } - - @GetMapping("/globalfilters") - public Mono> globalfilters() { - return getNamesToOrders(this.globalFilters); - } - - @GetMapping("/routefilters") - public Mono> routefilers() { - return getNamesToOrders(this.GatewayFilters); - } - - private Mono> getNamesToOrders(List list) { - return Flux.fromIterable(list).reduce(new HashMap<>(), this::putItem); - } - - private HashMap putItem(HashMap map, Object o) { - Integer order = null; - if (o instanceof Ordered) { - order = ((Ordered) o).getOrder(); - } - // filters.put(o.getClass().getName(), order); - map.put(o.toString(), order); - return map; + super(null, globalFilters, gatewayFilters, routeDefinitionWriter, routeLocator); } // TODO: Flush out routes without a definition @GetMapping("/routes") - public Mono>> routes() { - Mono> routeDefs = this.routeDefinitionLocator - .getRouteDefinitions().collectMap(RouteDefinition::getId); - Mono> routes = this.routeLocator.getRoutes().collectList(); - return Mono.zip(routeDefs, routes).map(tuple -> { - Map defs = tuple.getT1(); - List routeList = tuple.getT2(); - List> allRoutes = new ArrayList<>(); - - routeList.forEach(route -> { - HashMap r = new HashMap<>(); - r.put("route_id", route.getId()); - r.put("order", route.getOrder()); - - if (defs.containsKey(route.getId())) { - r.put("route_definition", defs.get(route.getId())); - } - else { - HashMap obj = new HashMap<>(); - - obj.put("predicate", route.getPredicate().toString()); - - if (!route.getFilters().isEmpty()) { - ArrayList filters = new ArrayList<>(); - for (GatewayFilter filter : route.getFilters()) { - filters.add(filter.toString()); - } - - obj.put("filters", filters); - } - - if (!obj.isEmpty()) { - r.put("route_object", obj); - } - } - allRoutes.add(r); - }); - - return allRoutes; - }); + public Flux> routes() { + return this.routeLocator.getRoutes().map(this::serialize); } - /* - * 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()))); - } + Map serialize(Route route) { + HashMap r = new HashMap<>(); + r.put("route_id", route.getId()); + r.put("uri", route.getUri().toString()); + r.put("order", route.getOrder()); + r.put("predicate", route.getPredicate().toString()); - @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())); + ArrayList filters = new ArrayList<>(); + + for (int i = 0; i < route.getFilters().size(); i++) { + GatewayFilter gatewayFilter = route.getFilters().get(i); + filters.add(gatewayFilter.toString()); + } + + r.put("filters", filters); + return r; } @GetMapping("/routes/{id}") - public Mono> route(@PathVariable String id) { - // TODO: missing RouteLocator - return this.routeDefinitionLocator.getRouteDefinitions() - .filter(route -> route.getId().equals(id)).singleOrEmpty() + public Mono>> route(@PathVariable String id) { + // @formatter:off + return this.routeLocator.getRoutes() + .filter(route -> route.getId().equals(id)) + .singleOrEmpty() + .map(this::serialize) .map(ResponseEntity::ok) .switchIfEmpty(Mono.just(ResponseEntity.notFound().build())); - } - - @GetMapping("/routes/{id}/combinedfilters") - public Mono> combinedfilters(@PathVariable String id) { - // TODO: missing global filters - return this.routeLocator.getRoutes().filter(route -> route.getId().equals(id)) - .reduce(new HashMap<>(), this::putItem); + // @formatter:on } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayLegacyControllerEndpoint.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayLegacyControllerEndpoint.java new file mode 100644 index 00000000..69c65152 --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/actuate/GatewayLegacyControllerEndpoint.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013-2019 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 + * + * https://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.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import reactor.core.publisher.Mono; + +import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; +import org.springframework.cloud.gateway.route.Route; +import org.springframework.cloud.gateway.route.RouteDefinition; +import org.springframework.cloud.gateway.route.RouteDefinitionLocator; +import org.springframework.cloud.gateway.route.RouteDefinitionWriter; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +/** + * @author Spencer Gibb + */ +@RestControllerEndpoint(id = "gateway") +public class GatewayLegacyControllerEndpoint extends AbstractGatewayControllerEndpoint { + + public GatewayLegacyControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, + List globalFilters, List GatewayFilters, + RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { + super(routeDefinitionLocator, globalFilters, GatewayFilters, + routeDefinitionWriter, routeLocator); + } + + @GetMapping("/routes") + public Mono>> routes() { + Mono> routeDefs = this.routeDefinitionLocator + .getRouteDefinitions().collectMap(RouteDefinition::getId); + Mono> routes = this.routeLocator.getRoutes().collectList(); + return Mono.zip(routeDefs, routes).map(tuple -> { + Map defs = tuple.getT1(); + List routeList = tuple.getT2(); + List> allRoutes = new ArrayList<>(); + + routeList.forEach(route -> { + HashMap r = new HashMap<>(); + r.put("route_id", route.getId()); + r.put("order", route.getOrder()); + + if (defs.containsKey(route.getId())) { + r.put("route_definition", defs.get(route.getId())); + } + else { + HashMap obj = new HashMap<>(); + + obj.put("predicate", route.getPredicate().toString()); + + if (!route.getFilters().isEmpty()) { + ArrayList filters = new ArrayList<>(); + for (GatewayFilter filter : route.getFilters()) { + filters.add(filter.toString()); + } + + obj.put("filters", filters); + } + + if (!obj.isEmpty()) { + r.put("route_object", obj); + } + } + allRoutes.add(r); + }); + + return allRoutes; + }); + } + + @GetMapping("/routes/{id}") + public Mono> route(@PathVariable String id) { + // TODO: missing RouteLocator + return this.routeDefinitionLocator.getRouteDefinitions() + .filter(route -> route.getId().equals(id)).singleOrEmpty() + .map(ResponseEntity::ok) + .switchIfEmpty(Mono.just(ResponseEntity.notFound().build())); + } + +} diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index 15423c35..a22ac5c5 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -39,11 +39,13 @@ 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.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; +import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint; import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter; import org.springframework.cloud.gateway.filter.ForwardPathFilter; import org.springframework.cloud.gateway.filter.ForwardRoutingFilter; @@ -120,6 +122,7 @@ import org.springframework.cloud.gateway.support.StringToZonedDateTimeConverter; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Primary; @@ -645,14 +648,39 @@ public class GatewayAutoConfiguration { protected static class GatewayActuatorConfiguration { @Bean + @ConditionalOnProperty("spring.cloud.gateway.actuator.verbose.enabled") @ConditionalOnEnabledEndpoint public GatewayControllerEndpoint gatewayControllerEndpoint( + List globalFilters, + List gatewayFilters, + RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { + return new GatewayControllerEndpoint(globalFilters, gatewayFilters, + routeDefinitionWriter, routeLocator); + } + + @Bean + @Conditional(OnVerboseDisabledCondition.class) + @ConditionalOnEnabledEndpoint + public GatewayLegacyControllerEndpoint gatewayLegacyControllerEndpoint( RouteDefinitionLocator routeDefinitionLocator, List globalFilters, - List GatewayFilters, + List gatewayFilters, RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { - return new GatewayControllerEndpoint(routeDefinitionLocator, globalFilters, - GatewayFilters, routeDefinitionWriter, routeLocator); + return new GatewayLegacyControllerEndpoint(routeDefinitionLocator, + globalFilters, gatewayFilters, routeDefinitionWriter, routeLocator); + } + + } + + private static class OnVerboseDisabledCondition extends NoneNestedConditions { + + OnVerboseDisabledCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnProperty("spring.cloud.gateway.actuator.verbose.enabled") + static class VerboseDisabled { + } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java index ec481d48..d97b23b3 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java @@ -51,11 +51,8 @@ public class OrderedGatewayFilter implements GatewayFilter, Ordered { @Override public String toString() { - final StringBuilder sb = new StringBuilder("OrderedGatewayFilter{"); - sb.append("delegate=").append(delegate); - sb.append(", order=").append(order); - sb.append('}'); - return sb.toString(); + return new StringBuilder("[").append(delegate).append(", order = ").append(order) + .append("]").toString(); } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactory.java index 0f624f52..e224c558 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactory.java @@ -16,8 +16,14 @@ package org.springframework.cloud.gateway.filter.factory; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @author Spencer Gibb @@ -27,11 +33,21 @@ public class AddRequestHeaderGatewayFilterFactory @Override public GatewayFilter apply(NameValueConfig config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest().mutate() - .header(config.getName(), config.getValue()).build(); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest().mutate() + .header(config.getName(), config.getValue()).build(); - return chain.filter(exchange.mutate().request(request).build()); + return chain.filter(exchange.mutate().request(request).build()); + } + + @Override + public String toString() { + return filterToStringCreator(AddRequestHeaderGatewayFilterFactory.this) + .append(config.getName(), config.getValue()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactory.java index 9e145094..95f2acbd 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactory.java @@ -18,11 +18,17 @@ package org.springframework.cloud.gateway.filter.factory; import java.net.URI; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; + /** * @author Spencer Gibb */ @@ -31,35 +37,45 @@ public class AddRequestParameterGatewayFilterFactory @Override public GatewayFilter apply(NameValueConfig config) { - return (exchange, chain) -> { - URI uri = exchange.getRequest().getURI(); - StringBuilder query = new StringBuilder(); - String originalQuery = uri.getRawQuery(); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + URI uri = exchange.getRequest().getURI(); + StringBuilder query = new StringBuilder(); + String originalQuery = uri.getRawQuery(); - if (StringUtils.hasText(originalQuery)) { - query.append(originalQuery); - if (originalQuery.charAt(originalQuery.length() - 1) != '&') { - query.append('&'); + if (StringUtils.hasText(originalQuery)) { + query.append(originalQuery); + if (originalQuery.charAt(originalQuery.length() - 1) != '&') { + query.append('&'); + } + } + + // TODO urlencode? + query.append(config.getName()); + query.append('='); + query.append(config.getValue()); + + try { + URI newUri = UriComponentsBuilder.fromUri(uri) + .replaceQuery(query.toString()).build(true).toUri(); + + ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri) + .build(); + + return chain.filter(exchange.mutate().request(request).build()); + } + catch (RuntimeException ex) { + throw new IllegalStateException( + "Invalid URI query: \"" + query.toString() + "\""); } } - // TODO urlencode? - query.append(config.getName()); - query.append('='); - query.append(config.getValue()); - - try { - URI newUri = UriComponentsBuilder.fromUri(uri) - .replaceQuery(query.toString()).build(true).toUri(); - - ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri) - .build(); - - return chain.filter(exchange.mutate().request(request).build()); - } - catch (RuntimeException ex) { - throw new IllegalStateException( - "Invalid URI query: \"" + query.toString() + "\""); + @Override + public String toString() { + return filterToStringCreator(AddRequestParameterGatewayFilterFactory.this) + .append(config.getName(), config.getValue()).toString(); } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactory.java index 73980a95..9f262999 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactory.java @@ -16,7 +16,13 @@ package org.springframework.cloud.gateway.filter.factory; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @author Spencer Gibb @@ -26,10 +32,21 @@ public class AddResponseHeaderGatewayFilterFactory @Override public GatewayFilter apply(NameValueConfig config) { - return (exchange, chain) -> { - exchange.getResponse().getHeaders().add(config.getName(), config.getValue()); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + exchange.getResponse().getHeaders().add(config.getName(), + config.getValue()); - return chain.filter(exchange); + return chain.filter(exchange); + } + + @Override + public String toString() { + return filterToStringCreator(AddResponseHeaderGatewayFilterFactory.this) + .append(config.getName(), config.getValue()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactory.java index e4686833..db014b58 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactory.java @@ -23,7 +23,11 @@ import java.util.stream.Collectors; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.HttpHeaders; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /* Use case: Both your legacy backend and your API gateway add CORS header values. So, your consumer ends up with @@ -81,9 +85,22 @@ public class DedupeResponseHeaderGatewayFilterFactory extends @Override public GatewayFilter apply(Config config) { - return (exchange, chain) -> chain.filter(exchange).then(Mono.fromRunnable(() -> { - dedupe(exchange.getResponse().getHeaders(), config); - })); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + return chain.filter(exchange).then(Mono.fromRunnable( + () -> dedupe(exchange.getResponse().getHeaders(), config))); + } + + @Override + public String toString() { + return filterToStringCreator( + DedupeResponseHeaderGatewayFilterFactory.this) + .append(config.getName(), config.getStrategy()) + .toString(); + } + }; } public enum Strategy { diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java index db20c193..8156c77d 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java @@ -47,6 +47,7 @@ import org.springframework.web.util.UriComponentsBuilder; import static java.util.Collections.singletonList; import static java.util.Optional.ofNullable; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.containsEncodedParts; @@ -113,42 +114,55 @@ public class HystrixGatewayFilterFactory config.setter = Setter.withGroupKey(groupKey).andCommandKey(commandKey); } - return (exchange, chain) -> { - RouteHystrixCommand command = new RouteHystrixCommand(config.setter, - config.fallbackUri, exchange, chain); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + RouteHystrixCommand command = new RouteHystrixCommand(config.setter, + config.fallbackUri, exchange, chain); - return Mono.create(s -> { - Subscription sub = command.toObservable().subscribe(s::success, s::error, - s::success); - s.onCancel(sub::unsubscribe); - }).onErrorResume((Function>) throwable -> { - if (throwable instanceof HystrixRuntimeException) { - HystrixRuntimeException e = (HystrixRuntimeException) throwable; - HystrixRuntimeException.FailureType failureType = e.getFailureType(); + return Mono.create(s -> { + Subscription sub = command.toObservable().subscribe(s::success, + s::error, s::success); + s.onCancel(sub::unsubscribe); + }).onErrorResume((Function>) throwable -> { + if (throwable instanceof HystrixRuntimeException) { + HystrixRuntimeException e = (HystrixRuntimeException) throwable; + HystrixRuntimeException.FailureType failureType = e + .getFailureType(); - switch (failureType) { - case TIMEOUT: - return Mono.error(new TimeoutException()); - case COMMAND_EXCEPTION: { - Throwable cause = e.getCause(); + switch (failureType) { + case TIMEOUT: + return Mono.error(new TimeoutException()); + case COMMAND_EXCEPTION: { + Throwable cause = e.getCause(); - /* - * We forsake here the null check for cause as - * HystrixRuntimeException will always have a cause if the failure - * type is COMMAND_EXCEPTION. - */ - if (cause instanceof ResponseStatusException - || AnnotatedElementUtils.findMergedAnnotation( - cause.getClass(), ResponseStatus.class) != null) { - return Mono.error(cause); + /* + * We forsake here the null check for cause as + * HystrixRuntimeException will always have a cause if the + * failure type is COMMAND_EXCEPTION. + */ + if (cause instanceof ResponseStatusException + || AnnotatedElementUtils.findMergedAnnotation( + cause.getClass(), + ResponseStatus.class) != null) { + return Mono.error(cause); + } + } + default: + break; } } - default: - break; - } - } - return Mono.error(throwable); - }).then(); + return Mono.error(throwable); + }).then(); + } + + @Override + public String toString() { + return filterToStringCreator(HystrixGatewayFilterFactory.this) + .append("name", config.getName()) + .append("fallback", config.fallbackUri).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactory.java index 6858d48c..58f20a7f 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactory.java @@ -21,10 +21,14 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ALREADY_PREFIXED_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; @@ -54,29 +58,38 @@ public class PrefixPathGatewayFilterFactory @Override public GatewayFilter apply(Config config) { - return (exchange, chain) -> { + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + boolean alreadyPrefixed = exchange + .getAttributeOrDefault(GATEWAY_ALREADY_PREFIXED_ATTR, false); + if (alreadyPrefixed) { + return chain.filter(exchange); + } + exchange.getAttributes().put(GATEWAY_ALREADY_PREFIXED_ATTR, true); - boolean alreadyPrefixed = exchange - .getAttributeOrDefault(GATEWAY_ALREADY_PREFIXED_ATTR, false); - if (alreadyPrefixed) { - return chain.filter(exchange); - } - exchange.getAttributes().put(GATEWAY_ALREADY_PREFIXED_ATTR, true); + ServerHttpRequest req = exchange.getRequest(); + addOriginalRequestUrl(exchange, req.getURI()); + String newPath = config.prefix + req.getURI().getRawPath(); - ServerHttpRequest req = exchange.getRequest(); - addOriginalRequestUrl(exchange, req.getURI()); - String newPath = config.prefix + req.getURI().getRawPath(); + ServerHttpRequest request = req.mutate().path(newPath).build(); - ServerHttpRequest request = req.mutate().path(newPath).build(); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); + if (log.isTraceEnabled()) { + log.trace("Prefixed URI with: " + config.prefix + " -> " + + request.getURI()); + } - if (log.isTraceEnabled()) { - log.trace("Prefixed URI with: " + config.prefix + " -> " - + request.getURI()); + return chain.filter(exchange.mutate().request(request).build()); } - return chain.filter(exchange.mutate().request(request).build()); + @Override + public String toString() { + return filterToStringCreator(PrefixPathGatewayFilterFactory.this) + .append("prefix", config.getPrefix()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactory.java index 88ac7aca..e5b7fcdc 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactory.java @@ -16,8 +16,13 @@ package org.springframework.cloud.gateway.filter.factory; -import org.springframework.cloud.gateway.filter.GatewayFilter; +import reactor.core.publisher.Mono; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.PRESERVE_HOST_HEADER_ATTRIBUTE; /** @@ -31,9 +36,19 @@ public class PreserveHostHeaderGatewayFilterFactory extends AbstractGatewayFilte } public GatewayFilter apply(Object config) { - return (exchange, chain) -> { - exchange.getAttributes().put(PRESERVE_HOST_HEADER_ATTRIBUTE, true); - return chain.filter(exchange); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + exchange.getAttributes().put(PRESERVE_HOST_HEADER_ATTRIBUTE, true); + return chain.filter(exchange); + } + + @Override + public String toString() { + return filterToStringCreator(PreserveHostHeaderGatewayFilterFactory.this) + .toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactory.java index 5ad46d0e..5d76f27d 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactory.java @@ -23,12 +23,15 @@ import java.util.List; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.support.HttpStatusHolder; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; +import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus; /** @@ -74,16 +77,33 @@ public class RedirectToGatewayFilterFactory } public GatewayFilter apply(HttpStatusHolder httpStatus, URI uri) { - return (exchange, chain) -> chain.filter(exchange).then(Mono.defer(() -> { - if (!exchange.getResponse().isCommitted()) { - setResponseStatus(exchange, httpStatus); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + if (!exchange.getResponse().isCommitted()) { + setResponseStatus(exchange, httpStatus); - final ServerHttpResponse response = exchange.getResponse(); - response.getHeaders().set(HttpHeaders.LOCATION, uri.toString()); - return response.setComplete(); + final ServerHttpResponse response = exchange.getResponse(); + response.getHeaders().set(HttpHeaders.LOCATION, uri.toString()); + return response.setComplete(); + } + return Mono.empty(); } - return Mono.empty(); - })); + + @Override + public String toString() { + String status; + if (httpStatus.getHttpStatus() != null) { + status = String.valueOf(httpStatus.getHttpStatus().value()); + } + else { + status = httpStatus.getStatus().toString(); + } + return filterToStringCreator(RedirectToGatewayFilterFactory.this) + .append(status, uri).toString(); + } + }; } public static class Config { diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactory.java index aa864b59..4cbad7d9 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactory.java @@ -19,8 +19,14 @@ package org.springframework.cloud.gateway.filter.factory; import java.util.Arrays; import java.util.List; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @author Spencer Gibb @@ -39,11 +45,22 @@ public class RemoveRequestHeaderGatewayFilterFactory @Override public GatewayFilter apply(NameConfig config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest().mutate() - .headers(httpHeaders -> httpHeaders.remove(config.getName())).build(); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest().mutate() + .headers(httpHeaders -> httpHeaders.remove(config.getName())) + .build(); - return chain.filter(exchange.mutate().request(request).build()); + return chain.filter(exchange.mutate().request(request).build()); + } + + @Override + public String toString() { + return filterToStringCreator(RemoveRequestHeaderGatewayFilterFactory.this) + .append("name", config.getName()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactory.java index 99ef296a..f506658b 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactory.java @@ -22,6 +22,10 @@ import java.util.List; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @author Spencer Gibb @@ -40,9 +44,21 @@ public class RemoveResponseHeaderGatewayFilterFactory @Override public GatewayFilter apply(NameConfig config) { - return (exchange, chain) -> chain.filter(exchange).then(Mono.fromRunnable(() -> { - exchange.getResponse().getHeaders().remove(config.getName()); - })); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + return chain.filter(exchange).then(Mono.fromRunnable(() -> exchange + .getResponse().getHeaders().remove(config.getName()))); + } + + @Override + public String toString() { + return filterToStringCreator( + RemoveResponseHeaderGatewayFilterFactory.this) + .append("name", config.getName()).toString(); + } + }; } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactory.java index d6b76098..51c65626 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactory.java @@ -27,8 +27,12 @@ import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; + /** * This filter changes the request uri by a request header. * @@ -49,6 +53,21 @@ public class RequestHeaderToRequestUriGatewayFilterFactory extends return Arrays.asList(NAME_KEY); } + @Override + public GatewayFilter apply(NameConfig config) { + // AbstractChangeRequestUriGatewayFilterFactory.apply() returns + // OrderedGatewayFilter + OrderedGatewayFilter gatewayFilter = (OrderedGatewayFilter) super.apply(config); + return new OrderedGatewayFilter(gatewayFilter, gatewayFilter.getOrder()) { + @Override + public String toString() { + return filterToStringCreator( + RequestHeaderToRequestUriGatewayFilterFactory.this) + .append("name", config.getName()).toString(); + } + }; + } + @Override protected Optional determineRequestUri(ServerWebExchange exchange, NameConfig config) { diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java index d3d5cb72..620ff423 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java @@ -16,11 +16,17 @@ package org.springframework.cloud.gateway.filter.factory; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * This filter blocks the request, if the request size is more than the permissible size. @@ -59,27 +65,39 @@ public class RequestSizeGatewayFilterFactory extends public GatewayFilter apply( RequestSizeGatewayFilterFactory.RequestSizeConfig requestSizeConfig) { requestSizeConfig.validate(); - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest(); - String contentLength = request.getHeaders().getFirst("content-length"); - if (!StringUtils.isEmpty(contentLength)) { - Long currentRequestSize = Long.valueOf(contentLength); - if (currentRequestSize > requestSizeConfig.getMaxSize()) { - exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE); - if (!exchange.getResponse().isCommitted()) { - exchange.getResponse().getHeaders().add("errorMessage", - getErrorMessage(currentRequestSize, - requestSizeConfig.getMaxSize())); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + String contentLength = request.getHeaders().getFirst("content-length"); + if (!StringUtils.isEmpty(contentLength)) { + Long currentRequestSize = Long.valueOf(contentLength); + if (currentRequestSize > requestSizeConfig.getMaxSize()) { + exchange.getResponse() + .setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE); + if (!exchange.getResponse().isCommitted()) { + exchange.getResponse().getHeaders().add("errorMessage", + getErrorMessage(currentRequestSize, + requestSizeConfig.getMaxSize())); + } + return exchange.getResponse().setComplete(); } - return exchange.getResponse().setComplete(); } + return chain.filter(exchange); + } + + @Override + public String toString() { + return filterToStringCreator(RequestSizeGatewayFilterFactory.this) + .append("max", requestSizeConfig.getMaxSize()).toString(); } - return chain.filter(exchange); }; } public static class RequestSizeConfig { + // TODO: use boot data size type private Long maxSize = 5000000L; public Long getMaxSize() { @@ -92,6 +110,7 @@ public class RequestSizeGatewayFilterFactory extends return this; } + // TODO: use validator annotation public void validate() { Assert.isTrue(this.maxSize != null && this.maxSize > 0, "maxSize must be greater than 0"); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java index 0c7096fe..567a589d 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java @@ -35,6 +35,7 @@ import reactor.retry.RetryContext; import org.springframework.cloud.gateway.event.EnableBodyCachingEvent; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.support.HasRouteId; import org.springframework.cloud.gateway.support.TimeoutException; import org.springframework.http.HttpMethod; @@ -43,6 +44,7 @@ import org.springframework.http.HttpStatus.Series; import org.springframework.util.Assert; import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_HEADER_NAMES; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ALREADY_ROUTED_ATTR; @@ -132,7 +134,25 @@ public class RetryGatewayFilterFactory .retryMax(retryConfig.getRetries()); } - return apply(retryConfig.getRouteId(), statusCodeRepeat, exceptionRetry); + GatewayFilter gatewayFilter = apply(retryConfig.getRouteId(), statusCodeRepeat, + exceptionRetry); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + return gatewayFilter.filter(exchange, chain); + } + + @Override + public String toString() { + return filterToStringCreator(RetryGatewayFilterFactory.this) + .append("retries", retryConfig.getRetries()) + .append("series", retryConfig.getSeries()) + .append("statuses", retryConfig.getStatuses()) + .append("methods", retryConfig.getMethods()) + .append("exceptions", retryConfig.getExceptions()).toString(); + } + }; } public boolean exceedsMaxIterations(ServerWebExchange exchange, diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactory.java index f6ed1832..1c337bef 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactory.java @@ -19,9 +19,14 @@ package org.springframework.cloud.gateway.filter.factory; import java.util.Arrays; import java.util.List; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.http.server.reactive.ServerHttpRequest; +import reactor.core.publisher.Mono; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; @@ -53,17 +58,27 @@ public class RewritePathGatewayFilterFactory @Override public GatewayFilter apply(Config config) { String replacement = config.replacement.replace("$\\", "$"); - return (exchange, chain) -> { - ServerHttpRequest req = exchange.getRequest(); - addOriginalRequestUrl(exchange, req.getURI()); - String path = req.getURI().getRawPath(); - String newPath = path.replaceAll(config.regexp, replacement); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest req = exchange.getRequest(); + addOriginalRequestUrl(exchange, req.getURI()); + String path = req.getURI().getRawPath(); + String newPath = path.replaceAll(config.regexp, replacement); - ServerHttpRequest request = req.mutate().path(newPath).build(); + ServerHttpRequest request = req.mutate().path(newPath).build(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI()); - return chain.filter(exchange.mutate().request(request).build()); + return chain.filter(exchange.mutate().request(request).build()); + } + + @Override + public String toString() { + return filterToStringCreator(RewritePathGatewayFilterFactory.this) + .append(config.getRegexp(), replacement).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactory.java index e547385c..0f933bc9 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactory.java @@ -22,8 +22,11 @@ import java.util.List; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; + /** * @author Vitaliy Pavlyuk */ @@ -51,9 +54,24 @@ public class RewriteResponseHeaderGatewayFilterFactory extends @Override public GatewayFilter apply(Config config) { - return (exchange, chain) -> chain.filter(exchange).then(Mono.fromRunnable(() -> { - rewriteHeader(exchange, config); - })); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + return chain.filter(exchange) + .then(Mono.fromRunnable(() -> rewriteHeader(exchange, config))); + } + + @Override + public String toString() { + return filterToStringCreator( + RewriteResponseHeaderGatewayFilterFactory.this) + .append("name", config.getName()) + .append("regexp", config.getRegexp()) + .append("replacement", config.getReplacement()) + .toString(); + } + }; } protected void rewriteHeader(ServerWebExchange exchange, Config config) { diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactory.java index 86c58e9b..72aee3a3 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactory.java @@ -16,9 +16,15 @@ package org.springframework.cloud.gateway.filter.factory; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebSession; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; + /** * Save the current {@link WebSession} before executing the rest of the * {@link org.springframework.cloud.gateway.filter.GatewayFilterChain}. @@ -33,8 +39,20 @@ public class SaveSessionGatewayFilterFactory extends AbstractGatewayFilterFactor @Override public GatewayFilter apply(Object config) { - return (exchange, chain) -> exchange.getSession().map(WebSession::save) - .then(chain.filter(exchange)); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + return exchange.getSession().map(WebSession::save) + .then(chain.filter(exchange)); + } + + @Override + public String toString() { + return filterToStringCreator(SaveSessionGatewayFilterFactory.this) + .toString(); + } + }; } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java index 0d0e3da5..d1d5c930 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java @@ -18,8 +18,14 @@ package org.springframework.cloud.gateway.filter.factory; import java.util.List; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.HttpHeaders; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * https://blog.appcanary.com/2017/http-security-headers.html. @@ -78,48 +84,60 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact public GatewayFilter apply(Object config) { // TODO: allow args to override properties - return (exchange, chain) -> { - HttpHeaders headers = exchange.getResponse().getHeaders(); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + HttpHeaders headers = exchange.getResponse().getHeaders(); - List disabled = properties.getDisable(); + List disabled = properties.getDisable(); - if (isEnabled(disabled, X_XSS_PROTECTION_HEADER)) { - headers.add(X_XSS_PROTECTION_HEADER, properties.getXssProtectionHeader()); + if (isEnabled(disabled, X_XSS_PROTECTION_HEADER)) { + headers.add(X_XSS_PROTECTION_HEADER, + properties.getXssProtectionHeader()); + } + + if (isEnabled(disabled, STRICT_TRANSPORT_SECURITY_HEADER)) { + headers.add(STRICT_TRANSPORT_SECURITY_HEADER, + properties.getStrictTransportSecurity()); + } + + if (isEnabled(disabled, X_FRAME_OPTIONS_HEADER)) { + headers.add(X_FRAME_OPTIONS_HEADER, properties.getFrameOptions()); + } + + if (isEnabled(disabled, X_CONTENT_TYPE_OPTIONS_HEADER)) { + headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, + properties.getContentTypeOptions()); + } + + if (isEnabled(disabled, REFERRER_POLICY_HEADER)) { + headers.add(REFERRER_POLICY_HEADER, properties.getReferrerPolicy()); + } + + if (isEnabled(disabled, CONTENT_SECURITY_POLICY_HEADER)) { + headers.add(CONTENT_SECURITY_POLICY_HEADER, + properties.getContentSecurityPolicy()); + } + + if (isEnabled(disabled, X_DOWNLOAD_OPTIONS_HEADER)) { + headers.add(X_DOWNLOAD_OPTIONS_HEADER, + properties.getDownloadOptions()); + } + + if (isEnabled(disabled, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)) { + headers.add(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, + properties.getPermittedCrossDomainPolicies()); + } + + return chain.filter(exchange); } - if (isEnabled(disabled, STRICT_TRANSPORT_SECURITY_HEADER)) { - headers.add(STRICT_TRANSPORT_SECURITY_HEADER, - properties.getStrictTransportSecurity()); + @Override + public String toString() { + return filterToStringCreator(SecureHeadersGatewayFilterFactory.this) + .toString(); } - - if (isEnabled(disabled, X_FRAME_OPTIONS_HEADER)) { - headers.add(X_FRAME_OPTIONS_HEADER, properties.getFrameOptions()); - } - - if (isEnabled(disabled, X_CONTENT_TYPE_OPTIONS_HEADER)) { - headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, - properties.getContentTypeOptions()); - } - - if (isEnabled(disabled, REFERRER_POLICY_HEADER)) { - headers.add(REFERRER_POLICY_HEADER, properties.getReferrerPolicy()); - } - - if (isEnabled(disabled, CONTENT_SECURITY_POLICY_HEADER)) { - headers.add(CONTENT_SECURITY_POLICY_HEADER, - properties.getContentSecurityPolicy()); - } - - if (isEnabled(disabled, X_DOWNLOAD_OPTIONS_HEADER)) { - headers.add(X_DOWNLOAD_OPTIONS_HEADER, properties.getDownloadOptions()); - } - - if (isEnabled(disabled, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)) { - 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/SetPathGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactory.java index b0b90909..303841bf 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactory.java @@ -21,10 +21,15 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriTemplate; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.getUriTemplateVariables; @@ -53,20 +58,30 @@ public class SetPathGatewayFilterFactory public GatewayFilter apply(Config config) { UriTemplate uriTemplate = new UriTemplate(config.template); - return (exchange, chain) -> { - ServerHttpRequest req = exchange.getRequest(); - addOriginalRequestUrl(exchange, req.getURI()); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest req = exchange.getRequest(); + addOriginalRequestUrl(exchange, req.getURI()); - Map uriVariables = getUriTemplateVariables(exchange); + Map uriVariables = getUriTemplateVariables(exchange); - URI uri = uriTemplate.expand(uriVariables); - String newPath = uri.getRawPath(); + URI uri = uriTemplate.expand(uriVariables); + String newPath = uri.getRawPath(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri); - ServerHttpRequest request = req.mutate().path(newPath).build(); + ServerHttpRequest request = req.mutate().path(newPath).build(); - return chain.filter(exchange.mutate().request(request).build()); + return chain.filter(exchange.mutate().request(request).build()); + } + + @Override + public String toString() { + return filterToStringCreator(SetPathGatewayFilterFactory.this) + .append("template", config.getTemplate()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactory.java index 4f1555a3..71a743f8 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactory.java @@ -16,8 +16,14 @@ package org.springframework.cloud.gateway.filter.factory; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @author Spencer Gibb @@ -27,12 +33,23 @@ public class SetRequestHeaderGatewayFilterFactory @Override public GatewayFilter apply(NameValueConfig config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest().mutate() - .headers(httpHeaders -> httpHeaders.set(config.name, config.value)) - .build(); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest().mutate() + .headers( + httpHeaders -> httpHeaders.set(config.name, config.value)) + .build(); - return chain.filter(exchange.mutate().request(request).build()); + return chain.filter(exchange.mutate().request(request).build()); + } + + @Override + public String toString() { + return filterToStringCreator(SetRequestHeaderGatewayFilterFactory.this) + .append(config.getName(), config.getValue()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactory.java index 38a8f35e..ea09569e 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactory.java @@ -19,6 +19,10 @@ package org.springframework.cloud.gateway.filter.factory; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; /** * @author Spencer Gibb @@ -28,9 +32,20 @@ public class SetResponseHeaderGatewayFilterFactory @Override public GatewayFilter apply(NameValueConfig config) { - return (exchange, chain) -> chain.filter(exchange).then(Mono.fromRunnable(() -> { - exchange.getResponse().getHeaders().set(config.name, config.value); - })); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + return chain.filter(exchange).then(Mono.fromRunnable(() -> exchange + .getResponse().getHeaders().set(config.name, config.value))); + } + + @Override + public String toString() { + return filterToStringCreator(SetResponseHeaderGatewayFilterFactory.this) + .append(config.getName(), config.getValue()).toString(); + } + }; } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactory.java index 677b978c..f5ac35b6 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactory.java @@ -22,8 +22,11 @@ import java.util.List; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.support.HttpStatusHolder; +import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus; /** @@ -49,21 +52,31 @@ public class SetStatusGatewayFilterFactory @Override public GatewayFilter apply(Config config) { HttpStatusHolder statusHolder = HttpStatusHolder.parse(config.status); - return (exchange, chain) -> { - // option 1 (runs in filter order) - /* - * exchange.getResponse().beforeCommit(() -> { - * exchange.getResponse().setStatusCode(finalStatus); return Mono.empty(); }); - * return chain.filter(exchange); - */ + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain 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 - setResponseStatus(exchange, statusHolder); - })); + // 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 + setResponseStatus(exchange, statusHolder); + })); + } + + @Override + public String toString() { + return filterToStringCreator(SetStatusGatewayFilterFactory.this) + .append("status", config.getStatus()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactory.java index 7fc558c8..d19374b8 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactory.java @@ -20,10 +20,15 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import reactor.core.publisher.Mono; + import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; @@ -52,19 +57,30 @@ public class StripPrefixGatewayFilterFactory @Override public GatewayFilter apply(Config config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest(); - addOriginalRequestUrl(exchange, request.getURI()); - String path = request.getURI().getRawPath(); - String newPath = "/" - + Arrays.stream(StringUtils.tokenizeToStringArray(path, "/")) - .skip(config.parts).collect(Collectors.joining("/")); - newPath += (newPath.length() > 1 && path.endsWith("/") ? "/" : ""); - ServerHttpRequest newRequest = request.mutate().path(newPath).build(); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + addOriginalRequestUrl(exchange, request.getURI()); + String path = request.getURI().getRawPath(); + String newPath = "/" + + Arrays.stream(StringUtils.tokenizeToStringArray(path, "/")) + .skip(config.parts).collect(Collectors.joining("/")); + newPath += (newPath.length() > 1 && path.endsWith("/") ? "/" : ""); + ServerHttpRequest newRequest = request.mutate().path(newPath).build(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI()); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, + newRequest.getURI()); - return chain.filter(exchange.mutate().request(newRequest).build()); + return chain.filter(exchange.mutate().request(newRequest).build()); + } + + @Override + public String toString() { + return filterToStringCreator(StripPrefixGatewayFilterFactory.this) + .append("parts", config.getParts()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java index 5645b3dc..a819a5de 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java @@ -23,6 +23,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.cloud.gateway.support.BodyInserterContext; import org.springframework.core.io.buffer.DataBuffer; @@ -37,8 +38,10 @@ import org.springframework.web.reactive.function.server.HandlerStrategies; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; + /** - * This filter is BETA and may be subject to change in a future release. + * GatewayFilter that modifies the request body. */ public class ModifyRequestBodyGatewayFilterFactory extends AbstractGatewayFilterFactory { @@ -58,40 +61,52 @@ public class ModifyRequestBodyGatewayFilterFactory extends @Override @SuppressWarnings("unchecked") public GatewayFilter apply(Config config) { - return (exchange, chain) -> { - Class inClass = config.getInClass(); - ServerRequest serverRequest = ServerRequest.create(exchange, - this.messageReaders); + return new GatewayFilter() { + @Override + public Mono filter(ServerWebExchange exchange, + GatewayFilterChain chain) { + Class inClass = config.getInClass(); + ServerRequest serverRequest = ServerRequest.create(exchange, + messageReaders); - // TODO: flux or mono - Mono modifiedBody = serverRequest.bodyToMono(inClass) - // .log("modify_request_mono", Level.INFO) - .flatMap(o -> config.rewriteFunction.apply(exchange, o)); + // TODO: flux or mono + Mono modifiedBody = serverRequest.bodyToMono(inClass) + // .log("modify_request_mono", Level.INFO) + .flatMap(o -> config.rewriteFunction.apply(exchange, o)); - BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, - config.getOutClass()); - HttpHeaders headers = new HttpHeaders(); - headers.putAll(exchange.getRequest().getHeaders()); + BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, + config.getOutClass()); + HttpHeaders headers = new HttpHeaders(); + headers.putAll(exchange.getRequest().getHeaders()); - // the new content type will be computed by bodyInserter - // and then set in the request decorator - headers.remove(HttpHeaders.CONTENT_LENGTH); + // the new content type will be computed by bodyInserter + // and then set in the request decorator + headers.remove(HttpHeaders.CONTENT_LENGTH); - // if the body is changing content types, set it here, to the bodyInserter - // will know about it - if (config.getContentType() != null) { - headers.set(HttpHeaders.CONTENT_TYPE, config.getContentType()); + // if the body is changing content types, set it here, to the bodyInserter + // will know about it + if (config.getContentType() != null) { + headers.set(HttpHeaders.CONTENT_TYPE, config.getContentType()); + } + CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage( + exchange, headers); + return bodyInserter.insert(outputMessage, new BodyInserterContext()) + // .log("modify_request", Level.INFO) + .then(Mono.defer(() -> { + ServerHttpRequest decorator = decorate(exchange, headers, + outputMessage); + return chain + .filter(exchange.mutate().request(decorator).build()); + })); } - CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, - headers); - return bodyInserter.insert(outputMessage, new BodyInserterContext()) - // .log("modify_request", Level.INFO) - .then(Mono.defer(() -> { - ServerHttpRequest decorator = decorate(exchange, headers, - outputMessage); - return chain.filter(exchange.mutate().request(decorator).build()); - })); + @Override + public String toString() { + return filterToStringCreator(ModifyRequestBodyGatewayFilterFactory.this) + .append("Content type", config.getContentType()) + .append("In class", config.getInClass()) + .append("Out class", config.getOutClass()).toString(); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java index ed135157..9ec7514f 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java @@ -26,6 +26,7 @@ import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; import org.springframework.cloud.gateway.support.BodyInserterContext; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; @@ -38,10 +39,11 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR; /** - * This filter is BETA and may be subject to change in a future release. + * GatewayFilter that modifies the respons body. */ public class ModifyResponseBodyGatewayFilterFactory extends AbstractGatewayFilterFactory { @@ -57,7 +59,10 @@ public class ModifyResponseBodyGatewayFilterFactory extends @Override public GatewayFilter apply(Config config) { - return new ModifyResponseGatewayFilter(config); + ModifyResponseGatewayFilter gatewayFilter = new ModifyResponseGatewayFilter( + config); + gatewayFilter.setFactory(this); + return gatewayFilter; } public static class Config { @@ -142,12 +147,13 @@ public class ModifyResponseBodyGatewayFilterFactory extends private final Config config; + private GatewayFilterFactory gatewayFilterFactory; + public ModifyResponseGatewayFilter(Config config) { this.config = config; } @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange.mutate().response(decorate(exchange)).build()); } @@ -212,6 +218,20 @@ public class ModifyResponseBodyGatewayFilterFactory extends return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1; } + @Override + public String toString() { + Object obj = (this.gatewayFilterFactory != null) ? this.gatewayFilterFactory + : this; + return filterToStringCreator(obj) + .append("New content type", config.getNewContentType()) + .append("In class", config.getInClass()) + .append("Out class", config.getOutClass()).toString(); + } + + public void setFactory(GatewayFilterFactory gatewayFilterFactory) { + this.gatewayFilterFactory = gatewayFilterFactory; + } + } } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/AsyncPredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/AsyncPredicate.java index 88c1d1d0..505e1e67 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/AsyncPredicate.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/AsyncPredicate.java @@ -17,12 +17,15 @@ package org.springframework.cloud.gateway.handler; import java.util.function.Function; +import java.util.function.Predicate; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate; import org.springframework.util.Assert; +import org.springframework.web.server.ServerWebExchange; /** * @author Ben Hale @@ -30,21 +33,115 @@ import org.springframework.util.Assert; public interface AsyncPredicate extends Function> { default AsyncPredicate and(AsyncPredicate other) { - Assert.notNull(other, "other must not be null"); - - return t -> Flux.zip(apply(t), other.apply(t)) - .map(tuple -> tuple.getT1() && tuple.getT2()); + return new AndAsyncPredicate<>(this, other); } default AsyncPredicate negate() { - return t -> Mono.from(apply(t)).map(b -> !b); + return new NegateAsyncPredicate<>(this); } default AsyncPredicate or(AsyncPredicate other) { - Assert.notNull(other, "other must not be null"); + return new OrAsyncPredicate<>(this, other); + } + + static AsyncPredicate from( + Predicate predicate) { + return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate)); + } + + class DefaultAsyncPredicate implements AsyncPredicate { + + private final Predicate delegate; + + public DefaultAsyncPredicate(Predicate delegate) { + this.delegate = delegate; + } + + @Override + public Publisher apply(T t) { + return Mono.just(delegate.test(t)); + } + + @Override + public String toString() { + return this.delegate.toString(); + } + + } + + class NegateAsyncPredicate implements AsyncPredicate { + + private final AsyncPredicate predicate; + + public NegateAsyncPredicate(AsyncPredicate predicate) { + Assert.notNull(predicate, "predicate AsyncPredicate must not be null"); + this.predicate = predicate; + } + + @Override + public Publisher apply(T t) { + return Mono.from(predicate.apply(t)).map(b -> !b); + } + + @Override + public String toString() { + return String.format("!%s", this.predicate); + } + + } + + class AndAsyncPredicate implements AsyncPredicate { + + private final AsyncPredicate left; + + private final AsyncPredicate right; + + public AndAsyncPredicate(AsyncPredicate left, + AsyncPredicate right) { + Assert.notNull(left, "Left AsyncPredicate must not be null"); + Assert.notNull(right, "Right AsyncPredicate must not be null"); + this.left = left; + this.right = right; + } + + @Override + public Publisher apply(T t) { + return Flux.zip(left.apply(t), right.apply(t)) + .map(tuple -> tuple.getT1() && tuple.getT2()); + } + + @Override + public String toString() { + return String.format("(%s && %s)", this.left, this.right); + } + + } + + class OrAsyncPredicate implements AsyncPredicate { + + private final AsyncPredicate left; + + private final AsyncPredicate right; + + public OrAsyncPredicate(AsyncPredicate left, + AsyncPredicate right) { + Assert.notNull(left, "Left AsyncPredicate must not be null"); + Assert.notNull(right, "Right AsyncPredicate must not be null"); + this.left = left; + this.right = right; + } + + @Override + public Publisher apply(T t) { + return Flux.zip(left.apply(t), right.apply(t)) + .map(tuple -> tuple.getT1() || tuple.getT2()); + } + + @Override + public String toString() { + return String.format("(%s || %s)", this.left, this.right); + } - return t -> Flux.zip(apply(t), other.apply(t)) - .map(tuple -> tuple.getT1() || tuple.getT2()); } } 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 index d3668dd9..3e10f89b 100644 --- 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 @@ -47,10 +47,17 @@ public class AfterRoutePredicateFactory @Override public Predicate apply(Config config) { - ZonedDateTime datetime = config.getDatetime(); - return exchange -> { - final ZonedDateTime now = ZonedDateTime.now(); - return now.isAfter(datetime); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange serverWebExchange) { + final ZonedDateTime now = ZonedDateTime.now(); + return now.isAfter(config.getDatetime()); + } + + @Override + public String toString() { + return String.format("After: %s", config.getDatetime()); + } }; } 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 index 2dbb7a01..d454763d 100644 --- 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 @@ -45,10 +45,17 @@ public class BeforeRoutePredicateFactory @Override public Predicate apply(Config config) { - ZonedDateTime datetime = config.getDatetime(); - return exchange -> { - final ZonedDateTime now = ZonedDateTime.now(); - return now.isBefore(datetime); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange serverWebExchange) { + final ZonedDateTime now = ZonedDateTime.now(); + return now.isBefore(config.getDatetime()); + } + + @Override + public String toString() { + return String.format("Before: %s", config.getDatetime()); + } }; } 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 index b241a4fe..9c79db20 100644 --- 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 @@ -54,14 +54,22 @@ public class BetweenRoutePredicateFactory @Override public Predicate apply(Config config) { - ZonedDateTime datetime1 = config.datetime1; - ZonedDateTime datetime2 = config.datetime2; - Assert.isTrue(datetime1.isBefore(datetime2), - config.datetime1 + " must be before " + config.datetime2); + Assert.isTrue(config.getDatetime1().isBefore(config.getDatetime2()), + config.getDatetime1() + " must be before " + config.getDatetime2()); - return exchange -> { - final ZonedDateTime now = ZonedDateTime.now(); - return now.isAfter(datetime1) && now.isBefore(datetime2); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange serverWebExchange) { + final ZonedDateTime now = ZonedDateTime.now(); + return now.isAfter(config.getDatetime1()) + && now.isBefore(config.getDatetime2()); + } + + @Override + public String toString() { + return String.format("Between: %s and %s", config.getDatetime1(), + config.getDatetime2()); + } }; } 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 index e53a0863..156a0ecd 100644 --- 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 @@ -53,18 +53,27 @@ public class CookieRoutePredicateFactory @Override public Predicate apply(Config config) { - return exchange -> { - List cookies = exchange.getRequest().getCookies() - .get(config.name); - if (cookies == null) { + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + List cookies = exchange.getRequest().getCookies() + .get(config.name); + if (cookies == null) { + return false; + } + for (HttpCookie cookie : cookies) { + if (cookie.getValue().matches(config.regexp)) { + return true; + } + } return false; } - for (HttpCookie cookie : cookies) { - if (cookie.getValue().matches(config.regexp)) { - return true; - } + + @Override + public String toString() { + return String.format("Cookie: name=%s regexp=%s", config.name, + config.regexp); } - return false; }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayPredicate.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayPredicate.java new file mode 100644 index 00000000..8b067a98 --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayPredicate.java @@ -0,0 +1,145 @@ +/* + * Copyright 2013-2019 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 + * + * https://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.util.Assert; +import org.springframework.web.server.ServerWebExchange; + +public interface GatewayPredicate extends Predicate { + + @Override + default Predicate and(Predicate other) { + return new AndGatewayPredicate(this, wrapIfNeeded(other)); + } + + @Override + default Predicate negate() { + return new NegateGatewayPredicate(this); + } + + @Override + default Predicate or(Predicate other) { + return new OrGatewayPredicate(this, wrapIfNeeded(other)); + } + + static GatewayPredicate wrapIfNeeded(Predicate other) { + GatewayPredicate right; + + if (other instanceof GatewayPredicate) { + right = (GatewayPredicate) other; + } + else { + right = new GatewayPredicateWrapper(other); + } + return right; + } + + class GatewayPredicateWrapper implements GatewayPredicate { + + private final Predicate delegate; + + public GatewayPredicateWrapper(Predicate delegate) { + Assert.notNull(delegate, "delegate GatewayPredicate must not be null"); + this.delegate = delegate; + } + + @Override + public boolean test(ServerWebExchange exchange) { + return this.delegate.test(exchange); + } + + @Override + public String toString() { + return this.delegate.getClass().getSimpleName(); + } + + } + + class NegateGatewayPredicate implements GatewayPredicate { + + private final GatewayPredicate predicate; + + public NegateGatewayPredicate(GatewayPredicate predicate) { + Assert.notNull(predicate, "predicate GatewayPredicate must not be null"); + this.predicate = predicate; + } + + @Override + public boolean test(ServerWebExchange t) { + return !this.predicate.test(t); + } + + @Override + public String toString() { + return String.format("!%s", this.predicate); + } + + } + + class AndGatewayPredicate implements GatewayPredicate { + + private final GatewayPredicate left; + + private final GatewayPredicate right; + + public AndGatewayPredicate(GatewayPredicate left, GatewayPredicate right) { + Assert.notNull(left, "Left GatewayPredicate must not be null"); + Assert.notNull(right, "Right GatewayPredicate must not be null"); + this.left = left; + this.right = right; + } + + @Override + public boolean test(ServerWebExchange t) { + return (this.left.test(t) && this.right.test(t)); + } + + @Override + public String toString() { + return String.format("(%s && %s)", this.left, this.right); + } + + } + + class OrGatewayPredicate implements GatewayPredicate { + + private final GatewayPredicate left; + + private final GatewayPredicate right; + + public OrGatewayPredicate(GatewayPredicate left, GatewayPredicate right) { + Assert.notNull(left, "Left GatewayPredicate must not be null"); + Assert.notNull(right, "Right GatewayPredicate must not be null"); + this.left = left; + this.right = right; + } + + @Override + public boolean test(ServerWebExchange t) { + return (this.left.test(t) || this.right.test(t)); + } + + @Override + public String toString() { + return String.format("(%s || %s)", this.left, this.right); + } + + } + +} 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 index 15c3aa94..32c749e0 100644 --- 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 @@ -56,20 +56,30 @@ public class HeaderRoutePredicateFactory public Predicate apply(Config config) { boolean hasRegex = !StringUtils.isEmpty(config.regexp); - return exchange -> { - List values = exchange.getRequest().getHeaders() - .getOrDefault(config.header, Collections.emptyList()); - if (values.isEmpty()) { - return false; - } - // values is now guaranteed to not be empty - if (hasRegex) { - // check if a header value matches - return values.stream().anyMatch(value -> value.matches(config.regexp)); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + List values = exchange.getRequest().getHeaders() + .getOrDefault(config.header, Collections.emptyList()); + if (values.isEmpty()) { + return false; + } + // values is now guaranteed to not be empty + if (hasRegex) { + // check if a header value matches + return values.stream() + .anyMatch(value -> value.matches(config.regexp)); + } + + // there is a value and since regexp is empty, we only check existence. + return true; } - // there is a value and since regexp is empty, we only check existence. - return true; + @Override + public String toString() { + return String.format("Header: %s regexp=%s", config.header, + config.regexp); + } }; } 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 index e75755bd..101db352 100644 --- 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 @@ -59,19 +59,27 @@ public class HostRoutePredicateFactory @Override public Predicate apply(Config config) { - return exchange -> { - String host = exchange.getRequest().getHeaders().getFirst("Host"); - Optional optionalPattern = config.getPatterns().stream() - .filter(pattern -> this.pathMatcher.match(pattern, host)).findFirst(); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + String host = exchange.getRequest().getHeaders().getFirst("Host"); + Optional optionalPattern = config.getPatterns().stream() + .filter(pattern -> pathMatcher.match(pattern, host)).findFirst(); - if (optionalPattern.isPresent()) { - Map variables = this.pathMatcher - .extractUriTemplateVariables(optionalPattern.get(), host); - ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables); - return true; + if (optionalPattern.isPresent()) { + Map variables = pathMatcher + .extractUriTemplateVariables(optionalPattern.get(), host); + ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables); + return true; + } + + return false; } - return false; + @Override + public String toString() { + return String.format("Hosts: %s", config.getPatterns()); + } }; } @@ -99,8 +107,9 @@ public class HostRoutePredicateFactory return patterns; } - public void setPatterns(List patterns) { + public Config setPatterns(List patterns) { this.patterns = patterns; + return this; } @Override 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 index fa5f5899..23249841 100644 --- 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 @@ -45,9 +45,17 @@ public class MethodRoutePredicateFactory @Override public Predicate apply(Config config) { - return exchange -> { - HttpMethod requestMethod = exchange.getRequest().getMethod(); - return requestMethod == config.getMethod(); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + HttpMethod requestMethod = exchange.getRequest().getMethod(); + return requestMethod == config.getMethod(); + } + + @Override + public String toString() { + return String.format("Method: %s", config.getMethod()); + } }; } 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 index bbb8f57d..2a1e8d12 100644 --- 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 @@ -87,22 +87,32 @@ public class PathRoutePredicateFactory pathPatterns.add(pathPattern); }); } - return exchange -> { - PathContainer path = parsePath(exchange.getRequest().getURI().getRawPath()); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + PathContainer path = parsePath( + exchange.getRequest().getURI().getRawPath()); - Optional optionalPathPattern = pathPatterns.stream() - .filter(pattern -> pattern.matches(path)).findFirst(); + Optional optionalPathPattern = pathPatterns.stream() + .filter(pattern -> pattern.matches(path)).findFirst(); - if (optionalPathPattern.isPresent()) { - PathPattern pathPattern = optionalPathPattern.get(); - traceMatch("Pattern", pathPattern.getPatternString(), path, true); - PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path); - putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables()); - return true; + if (optionalPathPattern.isPresent()) { + PathPattern pathPattern = optionalPathPattern.get(); + traceMatch("Pattern", pathPattern.getPatternString(), path, true); + PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path); + putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables()); + return true; + } + else { + traceMatch("Pattern", config.getPatterns(), path, false); + return false; + } } - else { - traceMatch("Pattern", config.getPatterns(), path, false); - return false; + + @Override + public String toString() { + return String.format("Paths: %s, match trailing slash: %b", + config.getPatterns(), config.isMatchOptionalTrailingSeparator()); } }; } 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 index efcb4e8f..15a38614 100644 --- 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 @@ -53,23 +53,33 @@ public class QueryRoutePredicateFactory @Override public Predicate apply(Config config) { - return exchange -> { - if (!StringUtils.hasText(config.regexp)) { - // check existence of header - return exchange.getRequest().getQueryParams().containsKey(config.param); - } + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + if (!StringUtils.hasText(config.regexp)) { + // check existence of header + return exchange.getRequest().getQueryParams() + .containsKey(config.param); + } - List values = exchange.getRequest().getQueryParams() - .get(config.param); - if (values == null) { + List values = exchange.getRequest().getQueryParams() + .get(config.param); + if (values == null) { + return false; + } + for (String value : values) { + if (value != null && value.matches(config.regexp)) { + return true; + } + } return false; } - for (String value : values) { - if (value != null && value.matches(config.regexp)) { - return true; - } + + @Override + public String toString() { + return String.format("Query: param=%s regexp=%s", config.getParam(), + config.getRegexp()); } - return false; }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactory.java index ece0aeb9..52f707f0 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactory.java @@ -22,6 +22,7 @@ import java.util.function.Predicate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.handler.AsyncPredicate; @@ -55,40 +56,49 @@ public class ReadBodyPredicateFactory @Override @SuppressWarnings("unchecked") public AsyncPredicate applyAsync(Config config) { - return exchange -> { - Class inClass = config.getInClass(); + return new AsyncPredicate() { + @Override + public Publisher apply(ServerWebExchange exchange) { + Class inClass = config.getInClass(); - Object cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY); - Mono modifiedBody; - // We can only read the body from the request once, once that happens if we - // try to read the body again an exception will be thrown. The below if/else - // caches the body object as a request attribute in the ServerWebExchange - // so if this filter is run more than once (due to more than one route - // using it) we do not try to read the request body multiple times - if (cachedBody != null) { - try { - boolean test = config.predicate.test(cachedBody); - exchange.getAttributes().put(TEST_ATTRIBUTE, test); - return Mono.just(test); - } - catch (ClassCastException e) { - if (log.isDebugEnabled()) { - log.debug("Predicate test failed because class in predicate " - + "does not match the cached body object", e); + Object cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY); + Mono modifiedBody; + // We can only read the body from the request once, once that happens if + // we try to read the body again an exception will be thrown. The below + // if/else caches the body object as a request attribute in the + // ServerWebExchange so if this filter is run more than once (due to more + // than one route using it) we do not try to read the request body + // multiple times + if (cachedBody != null) { + try { + boolean test = config.predicate.test(cachedBody); + exchange.getAttributes().put(TEST_ATTRIBUTE, test); + return Mono.just(test); } + catch (ClassCastException e) { + if (log.isDebugEnabled()) { + log.debug("Predicate test failed because class in predicate " + + "does not match the cached body object", e); + } + } + return Mono.just(false); + } + else { + return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, + (serverHttpRequest) -> ServerRequest + .create(exchange.mutate().request(serverHttpRequest) + .build(), messageReaders) + .bodyToMono(inClass) + .doOnNext(objectValue -> exchange.getAttributes().put( + CACHE_REQUEST_BODY_OBJECT_KEY, objectValue)) + .map(objectValue -> config.getPredicate() + .test(objectValue))); } - return Mono.just(false); } - else { - return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, - (serverHttpRequest) -> ServerRequest - .create(exchange.mutate().request(serverHttpRequest) - .build(), messageReaders) - .bodyToMono(inClass) - .doOnNext(objectValue -> exchange.getAttributes() - .put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue)) - .map(objectValue -> config.getPredicate() - .test(objectValue))); + + @Override + public String toString() { + return String.format("ReadBody: %s", config.getInClass()); } }; } 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 index 6fab9fd6..91810641 100644 --- 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 @@ -73,26 +73,34 @@ public class RemoteAddrRoutePredicateFactory public Predicate apply(Config config) { List sources = convert(config.sources); - return exchange -> { - InetSocketAddress remoteAddress = config.remoteAddressResolver - .resolve(exchange); - if (remoteAddress != null && remoteAddress.getAddress() != null) { - String hostAddress = remoteAddress.getAddress().getHostAddress(); - String host = exchange.getRequest().getURI().getHost(); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + InetSocketAddress remoteAddress = config.remoteAddressResolver + .resolve(exchange); + if (remoteAddress != null && remoteAddress.getAddress() != null) { + String hostAddress = remoteAddress.getAddress().getHostAddress(); + String host = exchange.getRequest().getURI().getHost(); - if (log.isDebugEnabled() && !hostAddress.equals(host)) { - log.debug("Remote addresses didn't match " + hostAddress + " != " - + host); - } + if (log.isDebugEnabled() && !hostAddress.equals(host)) { + log.debug("Remote addresses didn't match " + hostAddress + " != " + + host); + } - for (IpSubnetFilterRule source : sources) { - if (source.matches(remoteAddress)) { - return true; + for (IpSubnetFilterRule source : sources) { + if (source.matches(remoteAddress)) { + return true; + } } } + + return false; } - return false; + @Override + public String toString() { + return String.format("RemoteAddrs: %s", config.getSources()); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java index 428426c6..2ec03183 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactory.java @@ -84,31 +84,40 @@ public class WeightRoutePredicateFactory @Override public Predicate apply(WeightConfig config) { - return exchange -> { - Map weights = exchange.getAttributeOrDefault(WEIGHT_ATTR, - Collections.emptyMap()); + return new GatewayPredicate() { + @Override + public boolean test(ServerWebExchange exchange) { + Map weights = exchange.getAttributeOrDefault(WEIGHT_ATTR, + Collections.emptyMap()); - String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR); + String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR); - // all calculations and comparison against random num happened in - // WeightCalculatorWebFilter - String group = config.getGroup(); - if (weights.containsKey(group)) { + // all calculations and comparison against random num happened in + // WeightCalculatorWebFilter + String group = config.getGroup(); + if (weights.containsKey(group)) { - String chosenRoute = weights.get(group); - if (log.isTraceEnabled()) { - log.trace("in group weight: " + group + ", current route: " + routeId - + ", chosen route: " + chosenRoute); + String chosenRoute = weights.get(group); + if (log.isTraceEnabled()) { + log.trace("in group weight: " + group + ", current route: " + + routeId + ", chosen route: " + chosenRoute); + } + + return routeId.equals(chosenRoute); + } + else if (log.isTraceEnabled()) { + log.trace("no weights found for group: " + group + ", current route: " + + routeId); } - return routeId.equals(chosenRoute); - } - else if (log.isTraceEnabled()) { - log.trace("no weights found for group: " + group + ", current route: " - + routeId); + return false; } - return false; + @Override + public String toString() { + return String.format("Weight: %s %s", config.getGroup(), + config.getWeight()); + } }; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/GatewayToStringStyler.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/GatewayToStringStyler.java new file mode 100644 index 00000000..927c14ee --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/GatewayToStringStyler.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013-2019 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 + * + * https://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.function.Function; + +import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; +import org.springframework.core.style.DefaultToStringStyler; +import org.springframework.core.style.DefaultValueStyler; +import org.springframework.core.style.ToStringCreator; +import org.springframework.util.ClassUtils; + +public class GatewayToStringStyler extends DefaultToStringStyler { + + private static final GatewayToStringStyler FILTER_INSTANCE = new GatewayToStringStyler( + GatewayFilterFactory.class, NameUtils::normalizeFilterFactoryName); + + private final Function classNameFormatter; + + private final Class instanceClass; + + public static ToStringCreator filterToStringCreator(Object obj) { + return new ToStringCreator(obj, FILTER_INSTANCE); + } + + public GatewayToStringStyler(Class instanceClass, + Function classNameFormatter) { + super(new DefaultValueStyler()); + this.classNameFormatter = classNameFormatter; + this.instanceClass = instanceClass; + } + + @Override + public void styleStart(StringBuilder buffer, Object obj) { + if (!obj.getClass().isArray()) { + String shortName; + if (instanceClass.isInstance(obj)) { + shortName = classNameFormatter.apply(obj.getClass()); + } + else { + shortName = ClassUtils.getShortName(obj.getClass()); + } + buffer.append('[').append(shortName); + } + else { + buffer.append('['); + styleValue(buffer, obj); + } + } + +} 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 index c0aeb6e0..74957c8a 100644 --- 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 @@ -246,7 +246,7 @@ public final class ServerWebExchangeUtils { public static AsyncPredicate toAsyncPredicate( Predicate predicate) { Assert.notNull(predicate, "predicate must not be null"); - return t -> Mono.just(predicate.test(t)); + return AsyncPredicate.from(predicate); } @SuppressWarnings("unchecked") diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java index e33c70d4..c2735ded 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java @@ -27,6 +27,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; +import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; +import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.web.filter.reactive.HiddenHttpMethodFilter; @@ -36,9 +38,8 @@ public class GatewayAutoConfigurationTests { @Test public void noHiddenHttpMethodFilter() { - try (ConfigurableApplicationContext ctx = SpringApplication.run( - NoHiddenHttpMethodFilterConfig.class, "--spring.jmx.enabled=false", - "--server.port=0")) { + try (ConfigurableApplicationContext ctx = SpringApplication.run(Config.class, + "--spring.jmx.enabled=false", "--server.port=0")) { assertThat(ctx.getEnvironment() .getProperty("spring.webflux.hiddenmethod.filter.enabled")) .isEqualTo("false"); @@ -108,9 +109,30 @@ public class GatewayAutoConfigurationTests { }); } + @Test + public void legacyActuatorEnabledByDefault() { + try (ConfigurableApplicationContext ctx = SpringApplication.run(Config.class, + "--spring.jmx.enabled=false", "--server.port=0")) { + assertThat(ctx.getBeanNamesForType(GatewayControllerEndpoint.class)) + .isEmpty(); + assertThat(ctx.getBeanNamesForType(GatewayLegacyControllerEndpoint.class)) + .hasSize(1); + } + } + + @Test + public void verboseActuatorEnabled() { + try (ConfigurableApplicationContext ctx = SpringApplication.run(Config.class, + "--spring.jmx.enabled=false", "--server.port=0", + "--spring.cloud.gateway.actuator.verbose.enabled=true")) { + assertThat(ctx.getBeanNamesForType(GatewayControllerEndpoint.class)) + .hasSize(1); + } + } + @EnableAutoConfiguration @SpringBootConfiguration - protected static class NoHiddenHttpMethodFilterConfig { + protected static class Config { } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactoryTests.java index 00020866..74b20fae 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderGatewayFilterFactoryTests.java @@ -25,6 +25,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory.NameValueConfig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -68,6 +70,14 @@ public class AddRequestHeaderGatewayFilterFactoryTests extends BaseWebClientTest }); } + @Test + public void toStringFormat() { + NameValueConfig config = new NameValueConfig().setName("myname") + .setValue("myvalue"); + GatewayFilter filter = new AddRequestHeaderGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("myname").contains("myvalue"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactoryTests.java index dd840e66..03d247fd 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterGatewayFilterFactoryTests.java @@ -28,6 +28,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory.NameValueConfig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -107,6 +109,15 @@ public class AddRequestParameterGatewayFilterFactoryTests extends BaseWebClientT }); } + @Test + public void toStringFormat() { + NameValueConfig config = new NameValueConfig().setName("myname") + .setValue("myvalue"); + GatewayFilter filter = new AddRequestParameterGatewayFilterFactory() + .apply(config); + assertThat(filter.toString()).contains("myname").contains("myvalue"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddResponseParameterGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactoryTests.java similarity index 66% rename from spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddResponseParameterGatewayFilterFactoryTests.java rename to spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactoryTests.java index 5439e2b7..be476d83 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddResponseParameterGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderGatewayFilterFactoryTests.java @@ -25,6 +25,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory.NameValueConfig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -34,23 +36,42 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.util.UriComponentsBuilder; +import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) @DirtiesContext -public class AddResponseParameterGatewayFilterFactoryTests extends BaseWebClientTests { +public class AddResponseHeaderGatewayFilterFactoryTests extends BaseWebClientTests { @Test - public void testResposneParameterFilter() { + public void testResposneHeaderFilter() { + URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/headers") + .build(true).toUri(); + String host = "www.addresponseheader.org"; + String expectedValue = "Bar"; + testClient.get().uri(uri).header("Host", host).exchange().expectHeader() + .valueEquals("X-Request-Foo", expectedValue); + } + + @Test + public void testResposneHeaderFilterJavaDsl() { URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/get").build(true) .toUri(); - String host = "www.addresponseparamjava.org"; + String host = "www.addresponseheaderjava.org"; String expectedValue = "myresponsevalue"; testClient.get().uri(uri).header("Host", host).exchange().expectHeader() .valueEquals("example", expectedValue); } + @Test + public void toStringFormat() { + NameValueConfig config = new NameValueConfig().setName("myname") + .setValue("myvalue"); + GatewayFilter filter = new AddResponseHeaderGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("myname").contains("myvalue"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) @@ -61,8 +82,8 @@ public class AddResponseParameterGatewayFilterFactoryTests extends BaseWebClient @Bean public RouteLocator testRouteLocator(RouteLocatorBuilder builder) { - return builder.routes().route("add_response_param_java_test", - r -> r.path("/get").and().host("**.addresponseparamjava.org") + return builder.routes().route("add_response_header_java_test", + r -> r.path("/get").and().host("**.addresponseheaderjava.org") .filters(f -> f.prefixPath("/httpbin") .addResponseHeader("example", "myresponsevalue")) .uri(uri)) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactoryUnitTests.java index b1677d88..038bb8c5 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactoryUnitTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/DedupeResponseHeaderGatewayFilterFactoryUnitTests.java @@ -23,8 +23,13 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.http.HttpHeaders; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.Config; +import static org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.Strategy; + public class DedupeResponseHeaderGatewayFilterFactoryUnitTests { private static final String NAME_1 = HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN; @@ -33,14 +38,14 @@ public class DedupeResponseHeaderGatewayFilterFactoryUnitTests { private HttpHeaders headers; - private DedupeResponseHeaderGatewayFilterFactory.Config config; + private Config config; private DedupeResponseHeaderGatewayFilterFactory filter; @Before public void setUp() { headers = Mockito.mock(HttpHeaders.class); - config = new DedupeResponseHeaderGatewayFilterFactory.Config(); + config = new Config(); filter = new DedupeResponseHeaderGatewayFilterFactory(); } @@ -99,7 +104,7 @@ public class DedupeResponseHeaderGatewayFilterFactoryUnitTests { @Test public void dedupMultipleValuesRetainLast() { config.setName(NAME_1); - config.setStrategy(DedupeResponseHeaderGatewayFilterFactory.Strategy.RETAIN_LAST); + config.setStrategy(Strategy.RETAIN_LAST); Mockito.when(headers.get(NAME_1)).thenReturn(Arrays.asList("2", "3", "3", "4")); filter.dedupe(headers, config); Mockito.verify(headers).get(NAME_1); @@ -110,8 +115,7 @@ public class DedupeResponseHeaderGatewayFilterFactoryUnitTests { @Test public void dedupMultipleValuesRetainUnique() { config.setName(NAME_1); - config.setStrategy( - DedupeResponseHeaderGatewayFilterFactory.Strategy.RETAIN_UNIQUE); + config.setStrategy(Strategy.RETAIN_UNIQUE); Mockito.when(headers.get(NAME_1)).thenReturn(Arrays.asList("2", "3", "3", "4")); filter.dedupe(headers, config); Mockito.verify(headers).get(NAME_1); @@ -120,4 +124,15 @@ public class DedupeResponseHeaderGatewayFilterFactoryUnitTests { Mockito.verify(headers).put(Mockito.anyString(), Mockito.anyList()); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setName("myname"); + config.setStrategy(Strategy.RETAIN_LAST); + GatewayFilter filter = new DedupeResponseHeaderGatewayFilterFactory() + .apply(config); + assertThat(filter.toString()).contains("myname") + .contains(Strategy.RETAIN_LAST.toString()); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java index ee96093d..73d3a3cd 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java @@ -20,6 +20,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.http.HttpStatus; import org.springframework.test.annotation.DirtiesContext; @@ -28,6 +29,7 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.Assert; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.core.StringContains.containsString; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.cloud.gateway.filter.factory.ExceptionFallbackHandler.RETRIEVED_EXCEPTION; @@ -117,4 +119,12 @@ public class HystrixGatewayFilterFactoryTests extends BaseWebClientTests { }); } + @Test + public void toStringFormat() { + HystrixGatewayFilterFactory.Config config = new HystrixGatewayFilterFactory.Config() + .setName("myname").setFallbackUri("forward:/myfallback"); + GatewayFilter filter = new HystrixGatewayFilterFactory(null).apply(config); + assertThat(filter.toString()).contains("myname").contains("forward:/myfallback"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactoryTest.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactoryTest.java index 09046234..43bca9ed 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactoryTest.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PrefixPathGatewayFilterFactoryTest.java @@ -25,6 +25,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory.Config; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.web.server.ServerWebExchange; @@ -69,4 +70,12 @@ public class PrefixPathGatewayFilterFactoryTest { assertThat(uris).contains(request.getURI()); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setPrefix("myprefix"); + GatewayFilter filter = new PrefixPathGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("myprefix"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactoryTests.java index 704d5fb6..344dee8c 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/PreserveHostHeaderGatewayFilterFactoryTests.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -56,6 +57,12 @@ public class PreserveHostHeaderGatewayFilterFactoryTests extends BaseWebClientTe }); } + @Test + public void toStringFormat() { + GatewayFilter filter = new PreserveHostHeaderGatewayFilterFactory().apply(); + assertThat(filter.toString()).contains("PreserveHostHeader"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactoryTests.java index 1beb9183..cb843036 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RedirectToGatewayFilterFactoryTests.java @@ -22,6 +22,8 @@ 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.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -32,6 +34,7 @@ import org.springframework.http.HttpStatus; 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; @RunWith(SpringRunner.class) @@ -53,6 +56,15 @@ public class RedirectToGatewayFilterFactoryTests extends BaseWebClientTests { .valueEquals(HttpHeaders.LOCATION, "/index.html#/customers"); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setStatus("301"); + config.setUrl("http://newurl"); + GatewayFilter filter = new RedirectToGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("301").contains("http://newurl"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactoryTests.java index 40e16145..869fa46c 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderGatewayFilterFactoryTests.java @@ -24,6 +24,8 @@ 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.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory.NameConfig; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.context.annotation.Import; import org.springframework.test.annotation.DirtiesContext; @@ -49,6 +51,15 @@ public class RemoveRequestHeaderGatewayFilterFactoryTests extends BaseWebClientT }); } + @Test + public void toStringFormat() { + NameConfig config = new NameConfig(); + config.setName("myname"); + GatewayFilter filter = new RemoveRequestHeaderGatewayFilterFactory() + .apply(config); + assertThat(filter.toString()).contains("myname"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactoryTests.java index 1b050617..10468217 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderGatewayFilterFactoryTests.java @@ -22,11 +22,14 @@ 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.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory.NameConfig; 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; @RunWith(SpringRunner.class) @@ -41,6 +44,15 @@ public class RemoveResponseHeaderGatewayFilterFactoryTests extends BaseWebClient .doesNotExist("X-Request-Foo"); } + @Test + public void toStringFormat() { + NameConfig config = new NameConfig(); + config.setName("myname"); + GatewayFilter filter = new RemoveResponseHeaderGatewayFilterFactory() + .apply(config); + assertThat(filter.toString()).contains("myname"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactoryTests.java index 5703c079..ff6db8d6 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactoryTests.java @@ -24,6 +24,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory.NameConfig; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.web.server.ServerWebExchange; @@ -98,4 +99,13 @@ public class RequestHeaderToRequestUriGatewayFilterFactoryTests { assertThat(uri.toURL().toString()).isEqualTo("http://localhost"); } + @Test + public void toStringFormat() { + NameConfig config = new NameConfig(); + config.setName("myname"); + GatewayFilter filter = new RequestHeaderToRequestUriGatewayFilterFactory() + .apply(config); + assertThat(filter.toString()).contains("myname"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java index dc8b460c..abf6ba2b 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java @@ -23,6 +23,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory.RequestSizeConfig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -32,6 +34,7 @@ import org.springframework.http.HttpStatus; 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; /** @@ -54,6 +57,14 @@ public class RequestSizeGatewayFilterFactoryTest extends BaseWebClientTests { .valueMatches("errorMessage", responseMesssage); } + @Test + public void toStringFormat() { + RequestSizeConfig config = new RequestSizeConfig(); + config.setMaxSize(1000L); + GatewayFilter filter = new RequestSizeGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("max").contains("1000"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java index 4267b218..ca431a13 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java @@ -16,6 +16,7 @@ package org.springframework.cloud.gateway.filter.factory; +import java.io.IOException; import java.time.Duration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -33,6 +34,8 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory.RetryConfig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -111,6 +114,18 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest }); } + @Test + public void toStringFormat() { + RetryConfig config = new RetryConfig(); + config.setRetries(4); + config.setMethods(HttpMethod.GET); + config.setSeries(HttpStatus.Series.SERVER_ERROR); + config.setExceptions(IOException.class); + GatewayFilter filter = new RetryGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("4").contains("[GET]") + .contains("[SERVER_ERROR]").contains("[IOException]"); + } + @RestController @EnableAutoConfiguration @SpringBootConfiguration diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactoryTests.java index 6138dd91..f4bf1066 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathGatewayFilterFactoryTests.java @@ -25,6 +25,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory.Config; import org.springframework.http.HttpMethod; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; @@ -101,4 +102,11 @@ public class RewritePathGatewayFilterFactoryTests { assertThat(uri.getRawQuery()).isEqualTo("name=%E6%89%8E%E6%A0%B9"); } + @Test + public void toStringFormat() { + Config config = new Config().setRegexp("regexp1").setReplacement("replacement1"); + GatewayFilter filter = new RewritePathGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("regexp1").contains("replacement1"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactoryUnitTests.java index a4afc800..9fddff54 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactoryUnitTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteResponseHeaderGatewayFilterFactoryUnitTests.java @@ -19,6 +19,9 @@ package org.springframework.cloud.gateway.filter.factory; import org.junit.Before; import org.junit.Test; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory.Config; + import static org.assertj.core.api.Assertions.assertThat; public class RewriteResponseHeaderGatewayFilterFactoryUnitTests { @@ -42,4 +45,16 @@ public class RewriteResponseHeaderGatewayFilterFactoryUnitTests { .isEqualTo("/foo/cafe/wat/cafe"); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setName("myname"); + config.setRegexp("myregexp"); + config.setReplacement("myreplacement"); + GatewayFilter filter = new RewriteResponseHeaderGatewayFilterFactory() + .apply(config); + assertThat(filter.toString()).contains("myname").contains("myregexp") + .contains("myreplacement"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactoryTests.java index 9f1b70aa..8d21cafc 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SaveSessionGatewayFilterFactoryTests.java @@ -28,6 +28,7 @@ import reactor.test.StepVerifier; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; @@ -37,6 +38,7 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.server.WebSession; import org.springframework.web.server.session.WebSessionManager; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -70,6 +72,12 @@ public class SaveSessionGatewayFilterFactoryTests extends BaseWebClientTests { verify(mockWebSession).save(); } + @Test + public void toStringFormat() { + GatewayFilter filter = new SaveSessionGatewayFilterFactory().apply(""); + assertThat(filter.toString()).contains("SaveSession"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java index 5363737e..eedf2e3a 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.cloud.gateway.filter.factory; +import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -109,4 +110,11 @@ public class SecureHeadersGatewayFilterFactoryUnitTests { } + @Test + public void toStringFormat() { + GatewayFilter filter = new SecureHeadersGatewayFilterFactory( + new SecureHeadersProperties()).apply(""); + Assertions.assertThat(filter.toString()).contains("SecureHeaders"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactoryTests.java index 9f08e898..6de42e35 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathGatewayFilterFactoryTests.java @@ -26,6 +26,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory.Config; import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; @@ -102,4 +103,12 @@ public class SetPathGatewayFilterFactoryTests { assertThat(uris).contains(request.getURI()); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setTemplate("mytemplate"); + GatewayFilter filter = new SetPathGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("mytemplate"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactoryTests.java index db951907..e1e089b0 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestHeaderGatewayFilterFactoryTests.java @@ -25,6 +25,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory.NameValueConfig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -57,6 +59,14 @@ public class SetRequestHeaderGatewayFilterFactoryTests extends BaseWebClientTest }); } + @Test + public void toStringFormat() { + NameValueConfig config = new NameValueConfig().setName("myname") + .setValue("myvalue"); + GatewayFilter filter = new SetRequestHeaderGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("myname").contains("myvalue"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactoryTests.java index 7b0c83da..3eb1835d 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderGatewayFilterFactoryTests.java @@ -22,11 +22,14 @@ 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.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory.NameValueConfig; 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; @RunWith(SpringRunner.class) @@ -41,6 +44,14 @@ public class SetResponseHeaderGatewayFilterFactoryTests extends BaseWebClientTes .valueEquals("X-Request-Foo", "Bar"); } + @Test + public void toStringFormat() { + NameValueConfig config = new NameValueConfig().setName("myname") + .setValue("myvalue"); + GatewayFilter filter = new SetResponseHeaderGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("myname").contains("myvalue"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactoryTests.java index e37f6d59..77406d0e 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactoryTests.java @@ -24,6 +24,8 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -76,6 +78,14 @@ public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests { */ } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setStatus("401"); + GatewayFilter filter = new SetStatusGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("401"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactoryTests.java index a196945c..37cda3f4 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/StripPrefixGatewayFilterFactoryTests.java @@ -25,6 +25,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory.Config; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.web.server.ServerWebExchange; @@ -85,4 +86,12 @@ public class StripPrefixGatewayFilterFactoryTests { assertThat(uris).contains(request.getURI()); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setParts(2); + GatewayFilter filter = new StripPrefixGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("2"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactoryUnitTests.java new file mode 100644 index 00000000..668df25b --- /dev/null +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactoryUnitTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 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 + * + * https://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.rewrite; + +import org.junit.Test; + +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory.Config; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ModifyRequestBodyGatewayFilterFactoryUnitTests { + + @Test + public void toStringFormat() { + Config config = new Config(); + config.setInClass(String.class); + config.setOutClass(Integer.class); + config.setContentType("mycontenttype"); + GatewayFilter filter = new ModifyRequestBodyGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("String").contains("Integer") + .contains("mycontenttype"); + } + +} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryUnitTests.java new file mode 100644 index 00000000..dd7b9bdf --- /dev/null +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryUnitTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 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 + * + * https://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.rewrite; + +import org.junit.Test; + +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory.Config; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ModifyResponseBodyGatewayFilterFactoryUnitTests { + + @Test + public void toStringFormat() { + Config config = new Config(); + config.setInClass(String.class); + config.setOutClass(Integer.class); + config.setNewContentType("mycontenttype"); + GatewayFilter filter = new ModifyResponseBodyGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("String").contains("Integer") + .contains("mycontenttype"); + } + +} 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 index fd5851a4..efce32f4 100644 --- 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 @@ -18,9 +18,12 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.ZonedDateTime; import java.util.HashMap; +import java.util.function.Predicate; import org.junit.Test; +import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory.Config; + 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.bindConfig; @@ -84,9 +87,17 @@ public class AfterRoutePredicateFactoryTests { map.put(DATETIME_KEY, dateString); AfterRoutePredicateFactory factory = new AfterRoutePredicateFactory(); - AfterRoutePredicateFactory.Config config = bindConfig(map, factory); + Config config = bindConfig(map, factory); return factory.apply(config).test(getExchange()); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setDatetime(ZonedDateTime.now()); + Predicate predicate = new AfterRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("After: " + config.getDatetime()); + } + } 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 index 07d9352e..70b8a714 100644 --- 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 @@ -18,6 +18,7 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.ZonedDateTime; import java.util.HashMap; +import java.util.function.Predicate; import org.junit.Test; @@ -90,4 +91,12 @@ public class BeforeRoutePredicateFactoryTests { return factory.apply(config).test(getExchange()); } + @Test + public void toStringFormat() { + BeforeRoutePredicateFactory.Config config = new BeforeRoutePredicateFactory.Config(); + config.setDatetime(ZonedDateTime.now()); + Predicate predicate = new BeforeRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("Before: " + config.getDatetime()); + } + } 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 index c843c737..23e0b50f 100644 --- 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 @@ -19,6 +19,7 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; +import java.util.function.Predicate; import org.junit.Test; @@ -160,4 +161,14 @@ public class BetweenRoutePredicateFactoryTests { return factory.apply(config).test(getExchange()); } + @Test + public void toStringFormat() { + BetweenRoutePredicateFactory.Config config = new BetweenRoutePredicateFactory.Config(); + config.setDatetime1(ZonedDateTime.now()); + config.setDatetime2(ZonedDateTime.now().plusHours(1)); + Predicate predicate = new BetweenRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains( + "Between: " + config.getDatetime1() + " and " + config.getDatetime2()); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactoryTests.java index 1dae9241..34de5277 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/CookieRoutePredicateFactoryTests.java @@ -57,4 +57,14 @@ public class CookieRoutePredicateFactoryTests extends BaseWebClientTests { assertThat(predicate.test(exchange)).isTrue(); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setName("mycookie"); + config.setRegexp("myregexp"); + Predicate predicate = new CookieRoutePredicateFactory().apply(config); + assertThat(predicate.toString()) + .contains("Cookie: name=mycookie regexp=myregexp"); + } + } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java index e1200ee4..e66fb06f 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.gateway.handler.predicate; +import java.util.function.Predicate; + import org.junit.Test; import org.junit.runner.RunWith; @@ -24,6 +26,7 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; +import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -32,6 +35,7 @@ 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; @RunWith(SpringRunner.class) @@ -68,6 +72,15 @@ public class HeaderRoutePredicateFactoryTests extends BaseWebClientTests { .expectHeader().valueEquals(ROUTE_ID_HEADER, "header_exists_dsl"); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setHeader("myheader"); + config.setRegexp("myregexp"); + Predicate predicate = new HeaderRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("Header: myheader regexp=myregexp"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) 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 index 0a866dfa..c110781a 100644 --- 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 @@ -16,6 +16,9 @@ package org.springframework.cloud.gateway.handler.predicate; +import java.util.Arrays; +import java.util.function.Predicate; + import org.junit.Test; import org.junit.runner.RunWith; @@ -24,6 +27,7 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; +import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -32,6 +36,7 @@ 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; @RunWith(SpringRunner.class) @@ -75,6 +80,13 @@ public class HostRoutePredicateFactoryTests extends BaseWebClientTests { expectHostRoute("www.hostmultidsl2.org", "host_multi_dsl"); } + @Test + public void toStringFormat() { + Config config = new Config().setPatterns(Arrays.asList("pattern1", "pattern2")); + Predicate predicate = new HostRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("pattern1").contains("pattern2"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) 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 index bf763446..5a6652cd 100644 --- 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 @@ -16,6 +16,8 @@ package org.springframework.cloud.gateway.handler.predicate; +import java.util.function.Predicate; + import org.junit.Test; import org.junit.runner.RunWith; @@ -23,11 +25,14 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; +import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory.Config; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; 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; @RunWith(SpringRunner.class) @@ -44,6 +49,14 @@ public class MethodRoutePredicateFactoryTests extends BaseWebClientTests { .expectHeader().valueEquals(ROUTE_ID_HEADER, "method_test"); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setMethod(HttpMethod.GET); + Predicate predicate = new MethodRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("Method: " + config.getMethod()); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) 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 index b6493b85..5599b3e7 100644 --- 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 @@ -16,6 +16,9 @@ package org.springframework.cloud.gateway.handler.predicate; +import java.util.Arrays; +import java.util.function.Predicate; + import org.junit.Test; import org.junit.runner.RunWith; @@ -24,6 +27,7 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; +import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -33,6 +37,7 @@ import org.springframework.http.HttpHeaders; 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; @RunWith(SpringRunner.class) @@ -93,6 +98,15 @@ public class PathRoutePredicateFactoryTests extends BaseWebClientTests { .expectHeader().valueEquals(ROUTE_ID_HEADER, "path_test"); } + @Test + public void toStringFormat() { + Config config = new Config().setPatterns(Arrays.asList("patternA", "patternB")) + .setMatchOptionalTrailingSeparator(false); + Predicate predicate = new PathRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("patternA").contains("patternB") + .contains("false"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactoryTests.java index 87cb6ed9..d5406755 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/QueryRoutePredicateFactoryTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.gateway.handler.predicate; +import java.util.function.Predicate; + import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,6 +27,7 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.rule.OutputCapture; +import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; @@ -33,6 +36,7 @@ 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.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @@ -67,6 +71,15 @@ public class QueryRoutePredicateFactoryTests extends BaseWebClientTests { containsString("Error applying predicate for route: foo_query_param"))); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setParam("myparam"); + config.setRegexp("myregexp"); + Predicate predicate = new QueryRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("Query: param=myparam regexp=myregexp"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactoryTest.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactoryTest.java index 8b202500..d1fde657 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactoryTest.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactoryTest.java @@ -28,6 +28,8 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.cloud.gateway.handler.AsyncPredicate; +import org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.PermitAllSecurityConfiguration; @@ -45,7 +47,9 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.BodyInserters; +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; /** @@ -76,6 +80,15 @@ public class ReadBodyPredicateFactoryTest { } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setInClass(String.class); + AsyncPredicate predicate = new ReadBodyPredicateFactory() + .applyAsync(config); + assertThat(predicate.toString()).contains("ReadBody: " + config.getInClass()); + } + @EnableAutoConfiguration @SpringBootConfiguration @RibbonClients({ diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicateFactoryTests.java index a430eb0c..8b913fa1 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicateFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/RemoteAddrRoutePredicateFactoryTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.gateway.handler.predicate; import java.time.Duration; +import java.util.function.Predicate; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory.Config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver; @@ -39,6 +41,7 @@ import org.springframework.test.context.ActiveProfiles; 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; @@ -76,6 +79,14 @@ public class RemoteAddrRoutePredicateFactoryTests extends BaseWebClientTests { .expectComplete().verify(Duration.ofSeconds(20)); } + @Test + public void toStringFormat() { + Config config = new Config(); + config.setSources("1.2.3.4", "5.6.7.8"); + Predicate predicate = new RemoteAddrRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("RemoteAddrs: [1.2.3.4, 5.6.7.8]"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactoryIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactoryIntegrationTests.java index 47122b80..5e2a017c 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactoryIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/WeightRoutePredicateFactoryIntegrationTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.gateway.handler.predicate; import java.util.Random; +import java.util.function.Predicate; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,6 +30,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; +import org.springframework.cloud.gateway.support.WeightConfig; import org.springframework.cloud.gateway.test.BaseWebClientTests; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; @@ -36,6 +38,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @@ -72,6 +75,13 @@ public class WeightRoutePredicateFactoryIntegrationTests extends BaseWebClientTe .valueEquals(ROUTE_ID_HEADER, "weight_low_test"); } + @Test + public void toStringFormat() { + WeightConfig config = new WeightConfig("mygroup", "myroute", 5); + Predicate predicate = new WeightRoutePredicateFactory().apply(config); + assertThat(predicate.toString()).contains("Weight: mygroup 5"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java index 45e3a36d..53da140d 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java @@ -35,6 +35,7 @@ import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFac import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -74,10 +75,10 @@ public class RouteDefinitionRouteLocatorTests { .block(); List filters = routes.get(0).getFilters(); assertThat(filters).hasSize(3); - assertThat(getFilterClassName(filters.get(0))).startsWith("RemoveResponseHeader"); - assertThat(getFilterClassName(filters.get(1))).startsWith("AddResponseHeader"); + assertThat(getFilterClassName(filters.get(0))).contains("RemoveResponseHeader"); + assertThat(getFilterClassName(filters.get(1))).contains("AddResponseHeader"); assertThat(getFilterClassName(filters.get(2))) - .startsWith("RouteDefinitionRouteLocatorTests$TestOrderedGateway"); + .contains("RouteDefinitionRouteLocatorTests$TestOrderedGateway"); } private String getFilterClassName(GatewayFilter target) { @@ -85,7 +86,12 @@ public class RouteDefinitionRouteLocatorTests { return getFilterClassName(((OrderedGatewayFilter) target).getDelegate()); } else { - return target.getClass().getSimpleName(); + String simpleName = target.getClass().getSimpleName(); + if (StringUtils.isEmpty(simpleName)) { + // maybe a lambda using new toString methods + simpleName = target.toString(); + } + return simpleName; } } 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 index ae121a26..af616e47 100644 --- 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 @@ -25,10 +25,12 @@ import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitio import org.springframework.cloud.gateway.discovery.DiscoveryLocatorProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Profile; @SpringBootConfiguration @EnableAutoConfiguration +@Import(PermitAllSecurityConfiguration.class) public class GatewayTestApplication { public static void main(String[] args) { diff --git a/spring-cloud-gateway-core/src/test/resources/application.yml b/spring-cloud-gateway-core/src/test/resources/application.yml index 06ccc646..7840337a 100644 --- a/spring-cloud-gateway-core/src/test/resources/application.yml +++ b/spring-cloud-gateway-core/src/test/resources/application.yml @@ -384,3 +384,8 @@ eureka: client: enabled: false +management: + endpoints: + web: + exposure: + include: "*"