Move GlobalFilter back to FilteringWebHandler
This commit is contained in:
@@ -133,11 +133,11 @@ public class GatewayAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GlobalFilter> globalFilters,
|
||||
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
|
||||
List<WebFilterFactory> webFilterFactories,
|
||||
List<RequestPredicateFactory> predicates,
|
||||
RouteDefinitionLocator routeDefinitionLocator) {
|
||||
return new CachingRouteLocator(new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, globalFilters, webFilterFactories, properties));
|
||||
return new CachingRouteLocator(new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, webFilterFactories, properties));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -148,9 +148,8 @@ public class GatewayAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilteringWebHandler filteringWebHandler(GatewayProperties properties,
|
||||
RouteLocator routeLocator) {
|
||||
return new FilteringWebHandler(properties, routeLocator);
|
||||
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
|
||||
return new FilteringWebHandler(globalFilters);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway.filter;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class OrderedWebFilter implements WebFilter, Ordered {
|
||||
|
||||
private final WebFilter delegate;
|
||||
private final int order;
|
||||
|
||||
public OrderedWebFilter(WebFilter delegate, int order) {
|
||||
this.delegate = delegate;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.delegate.filter(exchange, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("OrderedWebFilter{");
|
||||
sb.append("delegate=").append(delegate);
|
||||
sb.append(", order=").append(order);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -17,16 +17,21 @@
|
||||
|
||||
package org.springframework.cloud.gateway.handler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.filter.OrderedWebFilter;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.config.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.WebFilterFactory;
|
||||
import org.springframework.cloud.gateway.route.Route;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
@@ -48,18 +53,27 @@ import reactor.core.publisher.Mono;
|
||||
public class FilteringWebHandler extends WebHandlerDecorator {
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final GatewayProperties gatewayProperties;
|
||||
private final RouteLocator routeLocator;
|
||||
private final List<WebFilter> globalFilters;
|
||||
|
||||
public FilteringWebHandler(GatewayProperties gatewayProperties, RouteLocator routeLocator) {
|
||||
this(new EmptyWebHandler(), gatewayProperties, routeLocator);
|
||||
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
|
||||
this(new EmptyWebHandler(), globalFilters);
|
||||
}
|
||||
|
||||
public FilteringWebHandler(WebHandler targetHandler, GatewayProperties gatewayProperties,
|
||||
RouteLocator routeLocator) {
|
||||
public FilteringWebHandler(WebHandler targetHandler, List<GlobalFilter> globalFilters) {
|
||||
super(targetHandler);
|
||||
this.gatewayProperties = gatewayProperties;
|
||||
this.routeLocator = routeLocator;
|
||||
this.globalFilters = loadFilters(globalFilters);
|
||||
}
|
||||
|
||||
private static List<WebFilter> loadFilters(List<GlobalFilter> filters) {
|
||||
return filters.stream()
|
||||
.map(filter -> {
|
||||
WebFilterAdapter webFilter = new WebFilterAdapter(filter);
|
||||
if (filter instanceof Ordered) {
|
||||
int order = ((Ordered) filter).getOrder();
|
||||
return new OrderedWebFilter(webFilter, order);
|
||||
}
|
||||
return webFilter;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/* TODO: relocate @EventListener(RefreshRoutesEvent.class)
|
||||
@@ -72,9 +86,14 @@ public class FilteringWebHandler extends WebHandlerDecorator {
|
||||
Optional<Route> route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
|
||||
List<WebFilter> webFilters = route.get().getWebFilters();
|
||||
|
||||
logger.debug("Sorted webFilterFactories: "+ webFilters);
|
||||
List<WebFilter> combined = new ArrayList<>(this.globalFilters);
|
||||
combined.addAll(webFilters);
|
||||
//TODO: needed or cached?
|
||||
AnnotationAwareOrderComparator.sort(combined);
|
||||
|
||||
return new DefaultWebFilterChain(webFilters, getDelegate()).filter(exchange);
|
||||
logger.debug("Sorted webFilterFactories: "+ combined);
|
||||
|
||||
return new DefaultWebFilterChain(combined, getDelegate()).filter(exchange);
|
||||
}
|
||||
|
||||
private static class DefaultWebFilterChain implements WebFilterChain {
|
||||
@@ -100,6 +119,29 @@ public class FilteringWebHandler extends WebHandlerDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
private static class WebFilterAdapter implements WebFilter {
|
||||
|
||||
private final GlobalFilter delegate;
|
||||
|
||||
public WebFilterAdapter(GlobalFilter delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.delegate.filter(exchange, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("WebFilterAdapter{");
|
||||
sb.append("delegate=").append(delegate);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class EmptyWebHandler implements WebHandler {
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange) {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.springframework.cloud.gateway.route;
|
||||
|
||||
import org.springframework.cloud.gateway.route.Route;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,38 +17,32 @@
|
||||
|
||||
package org.springframework.cloud.gateway.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.config.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.WebFilterFactory;
|
||||
import org.springframework.cloud.gateway.handler.predicate.RequestPredicateFactory;
|
||||
import org.springframework.cloud.gateway.filter.FilterDefinition;
|
||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||
import org.springframework.cloud.gateway.route.Route;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.tuple.Tuple;
|
||||
import org.springframework.tuple.TupleBuilder;
|
||||
import org.springframework.web.reactive.function.server.RequestPredicate;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.config.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.filter.FilterDefinition;
|
||||
import org.springframework.cloud.gateway.filter.OrderedWebFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.WebFilterFactory;
|
||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||
import org.springframework.cloud.gateway.handler.predicate.RequestPredicateFactory;
|
||||
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.RouteLocator;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.tuple.Tuple;
|
||||
import org.springframework.tuple.TupleBuilder;
|
||||
import org.springframework.web.reactive.function.server.RequestPredicate;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* {@link RouteLocator} that loads routes from a {@link RouteDefinitionLocator}
|
||||
@@ -59,26 +53,19 @@ public class RouteDefinitionRouteLocator implements RouteLocator {
|
||||
|
||||
private final RouteDefinitionLocator routeDefinitionLocator;
|
||||
private final Map<String, RequestPredicateFactory> requestPredicates = new LinkedHashMap<>();
|
||||
private final List<GlobalFilter> globalFilters;
|
||||
private final Map<String, WebFilterFactory> webFilterFactories = new HashMap<>();
|
||||
private final GatewayProperties gatewayProperties;
|
||||
|
||||
public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,
|
||||
List<RequestPredicateFactory> requestPredicates,
|
||||
List<GlobalFilter> globalFilters,
|
||||
List<WebFilterFactory> webFilterFactories,
|
||||
GatewayProperties gatewayProperties) {
|
||||
this.routeDefinitionLocator = routeDefinitionLocator;
|
||||
initFactories(requestPredicates);
|
||||
this.globalFilters = initList(globalFilters);
|
||||
webFilterFactories.forEach(factory -> this.webFilterFactories.put(factory.name(), factory));
|
||||
this.gatewayProperties = gatewayProperties;
|
||||
}
|
||||
|
||||
private static <T> List<T> initList(List<T> list) {
|
||||
return (list != null ? list : emptyList());
|
||||
}
|
||||
|
||||
private void initFactories(List<RequestPredicateFactory> requestPredicates) {
|
||||
requestPredicates.forEach(factory -> {
|
||||
String key = factory.name();
|
||||
@@ -124,17 +111,7 @@ public class RouteDefinitionRouteLocator implements RouteLocator {
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Collection<WebFilter> loadFilters(List<GlobalFilter> filters) {
|
||||
return filters.stream()
|
||||
.map(filter -> {
|
||||
WebFilterAdapter webFilter = new WebFilterAdapter(filter);
|
||||
if (filter instanceof Ordered) {
|
||||
int order = ((Ordered) filter).getOrder();
|
||||
return new OrderedWebFilter(webFilter, order);
|
||||
}
|
||||
return webFilter;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
private List<WebFilter> loadWebFilters(String id, List<FilterDefinition> filterDefinitions) {
|
||||
List<WebFilter> filters = filterDefinitions.stream()
|
||||
@@ -202,21 +179,20 @@ public class RouteDefinitionRouteLocator implements RouteLocator {
|
||||
}
|
||||
|
||||
private List<WebFilter> getFilters(RouteDefinition routeDefinition) {
|
||||
//TODO: probably a java 8 stream way of doing this
|
||||
List<WebFilter> combined = new ArrayList<>(loadFilters(this.globalFilters));
|
||||
List<WebFilter> filters = new ArrayList<>();
|
||||
|
||||
//TODO: support option to apply defaults after route specific filters?
|
||||
if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
|
||||
combined.addAll(loadWebFilters("defaultFilters",
|
||||
filters.addAll(loadWebFilters("defaultFilters",
|
||||
this.gatewayProperties.getDefaultFilters()));
|
||||
}
|
||||
|
||||
if (!routeDefinition.getFilters().isEmpty()) {
|
||||
combined.addAll(loadWebFilters(routeDefinition.getId(), routeDefinition.getFilters()));
|
||||
filters.addAll(loadWebFilters(routeDefinition.getId(), routeDefinition.getFilters()));
|
||||
}
|
||||
|
||||
AnnotationAwareOrderComparator.sort(combined);
|
||||
return combined;
|
||||
AnnotationAwareOrderComparator.sort(filters);
|
||||
return filters;
|
||||
}
|
||||
|
||||
private RequestPredicate combinePredicates(RouteDefinition routeDefinition) {
|
||||
@@ -247,56 +223,4 @@ public class RouteDefinitionRouteLocator implements RouteLocator {
|
||||
return found.apply(tuple);
|
||||
}
|
||||
|
||||
|
||||
private static class WebFilterAdapter implements WebFilter {
|
||||
|
||||
private final GlobalFilter delegate;
|
||||
|
||||
public WebFilterAdapter(GlobalFilter delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.delegate.filter(exchange, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("WebFilterAdapter{");
|
||||
sb.append("delegate=").append(delegate);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class OrderedWebFilter implements WebFilter, Ordered {
|
||||
|
||||
private final WebFilter delegate;
|
||||
private final int order;
|
||||
|
||||
public OrderedWebFilter(WebFilter delegate, int order) {
|
||||
this.delegate = delegate;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.delegate.filter(exchange, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("OrderedWebFilter{");
|
||||
sb.append("delegate=").append(delegate);
|
||||
sb.append(", order=").append(order);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ spring:
|
||||
gateway:
|
||||
default-filters:
|
||||
- RemoveNonProxyHeaders
|
||||
- PrefixPath=/httpbin
|
||||
routes:
|
||||
# =====================================
|
||||
- id: remove_request_header_test
|
||||
uri: http://httpbin.org:80
|
||||
# uri: http://httpbin.org:80
|
||||
uri: lb://testservice
|
||||
predicates:
|
||||
- Host=**.removenonproxyheaders.org
|
||||
- Path=/headers
|
||||
|
||||
@@ -17,22 +17,17 @@
|
||||
|
||||
package org.springframework.cloud.gateway.sample;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cloud.gateway.EnableGateway;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderWebFilterFactory;
|
||||
import org.springframework.cloud.gateway.route.Route;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.tuple.TupleBuilder;
|
||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.RouteDefinitionRouteLocator.loadFilters;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
@@ -44,13 +39,12 @@ import reactor.core.publisher.Flux;
|
||||
public class GatewaySampleApplication {
|
||||
|
||||
@Bean
|
||||
public RouteLocator customRouteLocator(List<GlobalFilter> globalFilters) {
|
||||
public RouteLocator customRouteLocator() {
|
||||
return () -> {
|
||||
Route route = Route.builder()
|
||||
.id("test")
|
||||
.uri("http://httpbin.org:80")
|
||||
.requestPredicate(RequestPredicates.path("/image/png"))
|
||||
.addAll(loadFilters(globalFilters))
|
||||
.add(new AddResponseHeaderWebFilterFactory()
|
||||
.apply(TupleBuilder.tuple().of("name", "X-TestHeader", "value", "foobar")))
|
||||
.build();
|
||||
|
||||
Reference in New Issue
Block a user