Adds toString() to filter factories and predicate factories. (#785)
This allows for easier debugging and visibility into configuration. Predicates needed custom implementations of and() or() and not() so that toString() could function. Actuator endpoint was updated to use the new toString(). To enable set `spring.cloud.gateway.actuator.verbose.enabled=true`. fixes gh-784
This commit is contained in:
@@ -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 <<global-filters,global filters>> applied to all routes, make a `GET` request to `/actuator/gateway/globalfilters`. The resulting response is similar to the following:
|
||||
|
||||
@@ -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<GlobalFilter> globalFilters;
|
||||
|
||||
protected List<GatewayFilterFactory> GatewayFilters;
|
||||
|
||||
protected RouteDefinitionWriter routeDefinitionWriter;
|
||||
|
||||
protected RouteLocator routeLocator;
|
||||
|
||||
protected ApplicationEventPublisher publisher;
|
||||
|
||||
public AbstractGatewayControllerEndpoint(
|
||||
RouteDefinitionLocator routeDefinitionLocator,
|
||||
List<GlobalFilter> globalFilters, List<GatewayFilterFactory> 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<Void> refresh() {
|
||||
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@GetMapping("/globalfilters")
|
||||
public Mono<HashMap<String, Object>> globalfilters() {
|
||||
return getNamesToOrders(this.globalFilters);
|
||||
}
|
||||
|
||||
@GetMapping("/routefilters")
|
||||
public Mono<HashMap<String, Object>> routefilers() {
|
||||
return getNamesToOrders(this.GatewayFilters);
|
||||
}
|
||||
|
||||
private <T> Mono<HashMap<String, Object>> getNamesToOrders(List<T> list) {
|
||||
return Flux.fromIterable(list).reduce(new HashMap<>(), this::putItem);
|
||||
}
|
||||
|
||||
private HashMap<String, Object> putItem(HashMap<String, Object> 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<ResponseEntity<Void>> save(@PathVariable String id,
|
||||
@RequestBody Mono<RouteDefinition> 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<ResponseEntity<Object>> 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<HashMap<String, Object>> combinedfilters(@PathVariable String id) {
|
||||
// TODO: missing global filters
|
||||
return this.routeLocator.getRoutes().filter(route -> route.getId().equals(id))
|
||||
.reduce(new HashMap<>(), this::putItem);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<GlobalFilter> globalFilters;
|
||||
|
||||
private List<GatewayFilterFactory> GatewayFilters;
|
||||
|
||||
private RouteDefinitionWriter routeDefinitionWriter;
|
||||
|
||||
private RouteLocator routeLocator;
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
public GatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator,
|
||||
List<GlobalFilter> globalFilters, List<GatewayFilterFactory> GatewayFilters,
|
||||
public GatewayControllerEndpoint(List<GlobalFilter> globalFilters,
|
||||
List<GatewayFilterFactory> 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<Void> refresh() {
|
||||
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@GetMapping("/globalfilters")
|
||||
public Mono<HashMap<String, Object>> globalfilters() {
|
||||
return getNamesToOrders(this.globalFilters);
|
||||
}
|
||||
|
||||
@GetMapping("/routefilters")
|
||||
public Mono<HashMap<String, Object>> routefilers() {
|
||||
return getNamesToOrders(this.GatewayFilters);
|
||||
}
|
||||
|
||||
private <T> Mono<HashMap<String, Object>> getNamesToOrders(List<T> list) {
|
||||
return Flux.fromIterable(list).reduce(new HashMap<>(), this::putItem);
|
||||
}
|
||||
|
||||
private HashMap<String, Object> putItem(HashMap<String, Object> 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<List<Map<String, Object>>> routes() {
|
||||
Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator
|
||||
.getRouteDefinitions().collectMap(RouteDefinition::getId);
|
||||
Mono<List<Route>> routes = this.routeLocator.getRoutes().collectList();
|
||||
return Mono.zip(routeDefs, routes).map(tuple -> {
|
||||
Map<String, RouteDefinition> defs = tuple.getT1();
|
||||
List<Route> routeList = tuple.getT2();
|
||||
List<Map<String, Object>> allRoutes = new ArrayList<>();
|
||||
|
||||
routeList.forEach(route -> {
|
||||
HashMap<String, Object> 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<String, Object> obj = new HashMap<>();
|
||||
|
||||
obj.put("predicate", route.getPredicate().toString());
|
||||
|
||||
if (!route.getFilters().isEmpty()) {
|
||||
ArrayList<String> 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<Map<String, Object>> 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<ResponseEntity<Void>> save(@PathVariable String id,
|
||||
@RequestBody Mono<RouteDefinition> 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<String, Object> serialize(Route route) {
|
||||
HashMap<String, Object> 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<ResponseEntity<Object>> 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<String> 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<ResponseEntity<RouteDefinition>> route(@PathVariable String id) {
|
||||
// TODO: missing RouteLocator
|
||||
return this.routeDefinitionLocator.getRouteDefinitions()
|
||||
.filter(route -> route.getId().equals(id)).singleOrEmpty()
|
||||
public Mono<ResponseEntity<Map<String, Object>>> 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<HashMap<String, Object>> 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<GlobalFilter> globalFilters, List<GatewayFilterFactory> GatewayFilters,
|
||||
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) {
|
||||
super(routeDefinitionLocator, globalFilters, GatewayFilters,
|
||||
routeDefinitionWriter, routeLocator);
|
||||
}
|
||||
|
||||
@GetMapping("/routes")
|
||||
public Mono<List<Map<String, Object>>> routes() {
|
||||
Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator
|
||||
.getRouteDefinitions().collectMap(RouteDefinition::getId);
|
||||
Mono<List<Route>> routes = this.routeLocator.getRoutes().collectList();
|
||||
return Mono.zip(routeDefs, routes).map(tuple -> {
|
||||
Map<String, RouteDefinition> defs = tuple.getT1();
|
||||
List<Route> routeList = tuple.getT2();
|
||||
List<Map<String, Object>> allRoutes = new ArrayList<>();
|
||||
|
||||
routeList.forEach(route -> {
|
||||
HashMap<String, Object> 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<String, Object> obj = new HashMap<>();
|
||||
|
||||
obj.put("predicate", route.getPredicate().toString());
|
||||
|
||||
if (!route.getFilters().isEmpty()) {
|
||||
ArrayList<String> 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<ResponseEntity<RouteDefinition>> 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()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<GlobalFilter> globalFilters,
|
||||
List<GatewayFilterFactory> gatewayFilters,
|
||||
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) {
|
||||
return new GatewayControllerEndpoint(globalFilters, gatewayFilters,
|
||||
routeDefinitionWriter, routeLocator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Conditional(OnVerboseDisabledCondition.class)
|
||||
@ConditionalOnEnabledEndpoint
|
||||
public GatewayLegacyControllerEndpoint gatewayLegacyControllerEndpoint(
|
||||
RouteDefinitionLocator routeDefinitionLocator,
|
||||
List<GlobalFilter> globalFilters,
|
||||
List<GatewayFilterFactory> GatewayFilters,
|
||||
List<GatewayFilterFactory> 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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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 {
|
||||
|
||||
@@ -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<Void> 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, Mono<Void>>) 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, Mono<Void>>) 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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 {
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<URI> determineRequestUri(ServerWebExchange exchange,
|
||||
NameConfig config) {
|
||||
|
||||
@@ -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<Void> 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");
|
||||
|
||||
@@ -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<Void> 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,
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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) {
|
||||
|
||||
@@ -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<Void> filter(ServerWebExchange exchange,
|
||||
GatewayFilterChain chain) {
|
||||
return exchange.getSession().map(WebSession::save)
|
||||
.then(chain.filter(exchange));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return filterToStringCreator(SaveSessionGatewayFilterFactory.this)
|
||||
.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Void> filter(ServerWebExchange exchange,
|
||||
GatewayFilterChain chain) {
|
||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||
|
||||
List<String> disabled = properties.getDisable();
|
||||
List<String> 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);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> filter(ServerWebExchange exchange,
|
||||
GatewayFilterChain chain) {
|
||||
ServerHttpRequest req = exchange.getRequest();
|
||||
addOriginalRequestUrl(exchange, req.getURI());
|
||||
|
||||
Map<String, String> uriVariables = getUriTemplateVariables(exchange);
|
||||
Map<String, String> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ModifyRequestBodyGatewayFilterFactory.Config> {
|
||||
@@ -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<Void> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ModifyResponseBodyGatewayFilterFactory.Config> {
|
||||
@@ -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<Config> gatewayFilterFactory;
|
||||
|
||||
public ModifyResponseGatewayFilter(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Mono<Void> 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<Config> gatewayFilterFactory) {
|
||||
this.gatewayFilterFactory = gatewayFilterFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<T> extends Function<T, Publisher<Boolean>> {
|
||||
|
||||
default AsyncPredicate<T> and(AsyncPredicate<? super T> 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<T> negate() {
|
||||
return t -> Mono.from(apply(t)).map(b -> !b);
|
||||
return new NegateAsyncPredicate<>(this);
|
||||
}
|
||||
|
||||
default AsyncPredicate<T> or(AsyncPredicate<? super T> other) {
|
||||
Assert.notNull(other, "other must not be null");
|
||||
return new OrAsyncPredicate<>(this, other);
|
||||
}
|
||||
|
||||
static AsyncPredicate<ServerWebExchange> from(
|
||||
Predicate<? super ServerWebExchange> predicate) {
|
||||
return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate));
|
||||
}
|
||||
|
||||
class DefaultAsyncPredicate<T> implements AsyncPredicate<T> {
|
||||
|
||||
private final Predicate<T> delegate;
|
||||
|
||||
public DefaultAsyncPredicate(Predicate<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Publisher<Boolean> apply(T t) {
|
||||
return Mono.just(delegate.test(t));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.delegate.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class NegateAsyncPredicate<T> implements AsyncPredicate<T> {
|
||||
|
||||
private final AsyncPredicate<? super T> predicate;
|
||||
|
||||
public NegateAsyncPredicate(AsyncPredicate<? super T> predicate) {
|
||||
Assert.notNull(predicate, "predicate AsyncPredicate must not be null");
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Publisher<Boolean> apply(T t) {
|
||||
return Mono.from(predicate.apply(t)).map(b -> !b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("!%s", this.predicate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AndAsyncPredicate<T> implements AsyncPredicate<T> {
|
||||
|
||||
private final AsyncPredicate<? super T> left;
|
||||
|
||||
private final AsyncPredicate<? super T> right;
|
||||
|
||||
public AndAsyncPredicate(AsyncPredicate<? super T> left,
|
||||
AsyncPredicate<? super T> 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<Boolean> 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<T> implements AsyncPredicate<T> {
|
||||
|
||||
private final AsyncPredicate<? super T> left;
|
||||
|
||||
private final AsyncPredicate<? super T> right;
|
||||
|
||||
public OrAsyncPredicate(AsyncPredicate<? super T> left,
|
||||
AsyncPredicate<? super T> 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<Boolean> 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,10 +47,17 @@ public class AfterRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,17 @@ public class BeforeRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -54,14 +54,22 @@ public class BetweenRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -53,18 +53,27 @@ public class CookieRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> apply(Config config) {
|
||||
return exchange -> {
|
||||
List<HttpCookie> cookies = exchange.getRequest().getCookies()
|
||||
.get(config.name);
|
||||
if (cookies == null) {
|
||||
return new GatewayPredicate() {
|
||||
@Override
|
||||
public boolean test(ServerWebExchange exchange) {
|
||||
List<HttpCookie> 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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ServerWebExchange> {
|
||||
|
||||
@Override
|
||||
default Predicate<ServerWebExchange> and(Predicate<? super ServerWebExchange> other) {
|
||||
return new AndGatewayPredicate(this, wrapIfNeeded(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
default Predicate<ServerWebExchange> negate() {
|
||||
return new NegateGatewayPredicate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
default Predicate<ServerWebExchange> or(Predicate<? super ServerWebExchange> other) {
|
||||
return new OrGatewayPredicate(this, wrapIfNeeded(other));
|
||||
}
|
||||
|
||||
static GatewayPredicate wrapIfNeeded(Predicate<? super ServerWebExchange> other) {
|
||||
GatewayPredicate right;
|
||||
|
||||
if (other instanceof GatewayPredicate) {
|
||||
right = (GatewayPredicate) other;
|
||||
}
|
||||
else {
|
||||
right = new GatewayPredicateWrapper(other);
|
||||
}
|
||||
return right;
|
||||
}
|
||||
|
||||
class GatewayPredicateWrapper implements GatewayPredicate {
|
||||
|
||||
private final Predicate<? super ServerWebExchange> delegate;
|
||||
|
||||
public GatewayPredicateWrapper(Predicate<? super ServerWebExchange> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,20 +56,30 @@ public class HeaderRoutePredicateFactory
|
||||
public Predicate<ServerWebExchange> apply(Config config) {
|
||||
boolean hasRegex = !StringUtils.isEmpty(config.regexp);
|
||||
|
||||
return exchange -> {
|
||||
List<String> 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<String> 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -59,19 +59,27 @@ public class HostRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> apply(Config config) {
|
||||
return exchange -> {
|
||||
String host = exchange.getRequest().getHeaders().getFirst("Host");
|
||||
Optional<String> 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<String> optionalPattern = config.getPatterns().stream()
|
||||
.filter(pattern -> pathMatcher.match(pattern, host)).findFirst();
|
||||
|
||||
if (optionalPattern.isPresent()) {
|
||||
Map<String, String> variables = this.pathMatcher
|
||||
.extractUriTemplateVariables(optionalPattern.get(), host);
|
||||
ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables);
|
||||
return true;
|
||||
if (optionalPattern.isPresent()) {
|
||||
Map<String, String> 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<String> patterns) {
|
||||
public Config setPatterns(List<String> patterns) {
|
||||
this.patterns = patterns;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,9 +45,17 @@ public class MethodRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<PathPattern> optionalPathPattern = pathPatterns.stream()
|
||||
.filter(pattern -> pattern.matches(path)).findFirst();
|
||||
Optional<PathPattern> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -53,23 +53,33 @@ public class QueryRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> 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<String> values = exchange.getRequest().getQueryParams()
|
||||
.get(config.param);
|
||||
if (values == null) {
|
||||
List<String> 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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ServerWebExchange> applyAsync(Config config) {
|
||||
return exchange -> {
|
||||
Class inClass = config.getInClass();
|
||||
return new AsyncPredicate<ServerWebExchange>() {
|
||||
@Override
|
||||
public Publisher<Boolean> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,26 +73,34 @@ public class RemoteAddrRoutePredicateFactory
|
||||
public Predicate<ServerWebExchange> apply(Config config) {
|
||||
List<IpSubnetFilterRule> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -84,31 +84,40 @@ public class WeightRoutePredicateFactory
|
||||
|
||||
@Override
|
||||
public Predicate<ServerWebExchange> apply(WeightConfig config) {
|
||||
return exchange -> {
|
||||
Map<String, String> weights = exchange.getAttributeOrDefault(WEIGHT_ATTR,
|
||||
Collections.emptyMap());
|
||||
return new GatewayPredicate() {
|
||||
@Override
|
||||
public boolean test(ServerWebExchange exchange) {
|
||||
Map<String, String> 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Class, String> classNameFormatter;
|
||||
|
||||
private final Class instanceClass;
|
||||
|
||||
public static ToStringCreator filterToStringCreator(Object obj) {
|
||||
return new ToStringCreator(obj, FILTER_INSTANCE);
|
||||
}
|
||||
|
||||
public GatewayToStringStyler(Class instanceClass,
|
||||
Function<Class, String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,7 +246,7 @@ public final class ServerWebExchangeUtils {
|
||||
public static AsyncPredicate<ServerWebExchange> toAsyncPredicate(
|
||||
Predicate<? super ServerWebExchange> predicate) {
|
||||
Assert.notNull(predicate, "predicate must not be null");
|
||||
return t -> Mono.just(predicate.test(t));
|
||||
return AsyncPredicate.from(predicate);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<ServerWebExchange> predicate = new ReadBodyPredicateFactory()
|
||||
.applyAsync(config);
|
||||
assertThat(predicate.toString()).contains("ReadBody: " + config.getInClass());
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@SpringBootConfiguration
|
||||
@RibbonClients({
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<GatewayFilter> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -384,3 +384,8 @@ eureka:
|
||||
client:
|
||||
enabled: false
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
|
||||
Reference in New Issue
Block a user