Add support for default filters.

fixes gh-23
This commit is contained in:
Spencer Gibb
2017-02-14 17:07:58 -07:00
parent 72f2fa9df5
commit e967d23755
5 changed files with 62 additions and 10 deletions

View File

@@ -84,9 +84,9 @@ public class GatewayAutoConfiguration {
}
@Bean
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters,
public FilteringWebHandler filteringWebHandler(GatewayProperties properties, List<GlobalFilter> globalFilters,
Map<String, RouteFilter> routeFilters) {
return new FilteringWebHandler(globalFilters, routeFilters);
return new FilteringWebHandler(properties, globalFilters, routeFilters);
}
@Bean

View File

@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.api.FilterDefinition;
import org.springframework.cloud.gateway.api.Route;
import javax.validation.Valid;
@@ -16,12 +17,17 @@ import javax.validation.constraints.NotNull;
public class GatewayProperties {
/**
* Map of route names to properties.
* List of Routes
*/
@NotNull
@Valid
private List<Route> routes = new ArrayList<>();
/**
* List of filter definitions that are applied to every route.
*/
private List<FilterDefinition> defaultFilters = new ArrayList<>();
public List<Route> getRoutes() {
return routes;
}
@@ -30,4 +36,11 @@ public class GatewayProperties {
this.routes = routes;
}
public List<FilterDefinition> getDefaultFilters() {
return defaultFilters;
}
public void setDefaultFilters(List<FilterDefinition> defaultFilters) {
this.defaultFilters = defaultFilters;
}
}

View File

@@ -28,7 +28,9 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.api.FilterDefinition;
import org.springframework.cloud.gateway.api.Route;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.route.RouteFilter;
import org.springframework.core.Ordered;
@@ -55,19 +57,21 @@ import reactor.core.publisher.Mono;
public class FilteringWebHandler extends WebHandlerDecorator {
protected final Log logger = LogFactory.getLog(getClass());
private final GatewayProperties gatewayProperties;
private final List<GlobalFilter> globalFilters;
private final Map<String, RouteFilter> routeFilters = new HashMap<>();
private final Map<String, List<WebFilter>> combinedFiltersForRoute = new HashMap<>();
public FilteringWebHandler(List<GlobalFilter> globalFilters,
public FilteringWebHandler(GatewayProperties gatewayProperties, List<GlobalFilter> globalFilters,
Map<String, RouteFilter> routeFilters) {
this(new EmptyWebHandler(), globalFilters, routeFilters);
this(new EmptyWebHandler(), gatewayProperties, globalFilters, routeFilters);
}
public FilteringWebHandler(WebHandler targetHandler, List<GlobalFilter> globalFilters,
public FilteringWebHandler(WebHandler targetHandler, GatewayProperties gatewayProperties, List<GlobalFilter> globalFilters,
Map<String, RouteFilter> routeFilters) {
super(targetHandler);
this.gatewayProperties = gatewayProperties;
this.globalFilters = initList(globalFilters);
routeFilters.forEach((name, def) -> this.routeFilters.put(normalizeName(name), def));
}
@@ -107,8 +111,14 @@ public class FilteringWebHandler extends WebHandlerDecorator {
//TODO: probably a java 8 stream way of doing this
combinedFilters = new ArrayList<>(loadFilters(this.globalFilters));
//TODO: support option to apply defaults after route specific filters?
if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
combinedFilters.addAll(loadWebFilters("defaultFilters",
this.gatewayProperties.getDefaultFilters()));
}
if (route.isPresent() && !route.get().getFilters().isEmpty()) {
combinedFilters.addAll(loadRouteFilters(route.get()));
combinedFilters.addAll(loadWebFilters(route.get().getId(), route.get().getFilters()));
}
AnnotationAwareOrderComparator.sort(combinedFilters);
@@ -129,8 +139,8 @@ public class FilteringWebHandler extends WebHandlerDecorator {
}).collect(Collectors.toList());
}
private List<WebFilter> loadRouteFilters(Route route) {
List<WebFilter> filters = route.getFilters().stream()
private List<WebFilter> loadWebFilters(String id, List<FilterDefinition> filterDefinitions) {
List<WebFilter> filters = filterDefinitions.stream()
.map(definition -> {
RouteFilter filter = this.routeFilters.get(definition.getName());
if (filter == null) {
@@ -143,7 +153,7 @@ public class FilteringWebHandler extends WebHandlerDecorator {
} else {
args = Collections.emptyList();
}
logger.debug("Route " + route.getId() + " applying filter " + args + " to " + definition.getName());
logger.debug("Route " + id + " applying filter " + args + " to " + definition.getName());
}
return filter.apply(definition.getArgs());
})

View File

@@ -9,11 +9,13 @@ import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.gateway.api.Route;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.route.SecureHeadersProperties;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
@@ -73,6 +75,9 @@ public class GatewayIntegrationTests {
private WebClient webClient;
private String baseUri;
@Autowired
private GatewayProperties properties;
@Before
public void setup() {
//TODO: how to set new ReactorClientHttpConnector()
@@ -187,6 +192,27 @@ public class GatewayIntegrationTests {
.verify();
}
@Test
public void defaultFiltersWorks() {
assertThat(this.properties.getDefaultFilters()).isNotEmpty();
Mono<ClientResponse> result = webClient.get()
.uri("/headers")
.header("Host", "www.addresponseheader.org")
.exchange();
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
assertThat(httpHeaders.getFirst("X-Response-Default-Foo"))
.isEqualTo("Default-Bar");
assertThat(httpHeaders.get("X-Response-Default-Foo")).hasSize(1);
})
.expectComplete()
.verify(DURATION);
}
@Test
public void hostRouteWorks() {
Mono<ClientResponse> result = webClient.get()

View File

@@ -2,6 +2,9 @@
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
routes:
# =====================================
- host_example_to_httpbin=http://httpbin.org:80, Host=**.example.org