From 14ea1244b22f5f5b2e4b3f11772da2fd68bdaf80 Mon Sep 17 00:00:00 2001 From: JesseEstum Date: Fri, 8 Mar 2024 13:03:33 -0600 Subject: [PATCH] Allow forcing order of filters through Java DSL configuration. (#3134) --- .../route/builder/GatewayFilterSpec.java | 21 ++++++++++++ .../route/builder/GatewayFilterSpecTests.java | 32 ++++++++++++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java index 273be579..e8ea794c 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java @@ -129,6 +129,27 @@ public class GatewayFilterSpec extends UriSpec { return this; } + /** + * Applies the filter to the route. + * @param gatewayFilter the filter to apply + * @param order the order to apply the filter + * @param forceOrder if true, then force the order even if the supplied + * {@link GatewayFilter} implements {@link Ordered} + * @return a {@link GatewayFilterSpec} that can be used to apply additional filters + */ + public GatewayFilterSpec filter(GatewayFilter gatewayFilter, int order, boolean forceOrder) { + if (gatewayFilter instanceof Ordered) { + if (!forceOrder) { + this.routeBuilder.filter(gatewayFilter); + log.warn("GatewayFilter already implements ordered " + gatewayFilter.getClass() + + "ignoring order parameter: " + order); + return this; + } + } + this.routeBuilder.filter(new OrderedGatewayFilter(gatewayFilter, order)); + return this; + } + /** * Applies the list of filters to the route. * @param gatewayFilters the filters to apply diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpecTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpecTests.java index e0f9d507..ac06d7f1 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpecTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpecTests.java @@ -41,24 +41,46 @@ public class GatewayFilterSpecTests { @Test public void orderedInterfaceRespected() { - testFilter(MyOrderedFilter.class, new MyOrderedFilter(), 1000); + testFilter(MyOrderedFilter.class, new MyOrderedFilter(), 1000, null, false); + } + + @Test + public void orderedInterfaceRespectedWhenOrderSpecified() { + testFilter(MyOrderedFilter.class, new MyOrderedFilter(), 1000, 5, false); } @Test public void unorderedWithDefaultOrder() { - testFilter(OrderedGatewayFilter.class, new MyUnorderedFilter(), 0); + testFilter(OrderedGatewayFilter.class, new MyUnorderedFilter(), 0, null, false); } - private void testFilter(Class type, GatewayFilter gatewayFilter, int order) { + @Test + public void forceOrderWithOrderedInterface() { + testFilter(OrderedGatewayFilter.class, new MyOrderedFilter(), 5, 5, true); + } + + private void testFilter(Class type, GatewayFilter gatewayFilter, int expectedOrder, + Integer specifiedOrder, Boolean forceOrder) { ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class); Route.AsyncBuilder routeBuilder = Route.async().id("123").uri("abc:123").predicate(exchange -> true); RouteLocatorBuilder.Builder routes = new RouteLocatorBuilder(context).routes(); GatewayFilterSpec spec = new GatewayFilterSpec(routeBuilder, routes); - spec.filter(gatewayFilter); + + if (specifiedOrder != null) { + if (forceOrder != null) { + spec.filter(gatewayFilter, specifiedOrder, forceOrder); + } + else { + spec.filter(gatewayFilter, specifiedOrder); + } + } + else { + spec.filter(gatewayFilter); + } Route route = routeBuilder.build(); assertThat(route.getFilters()).hasSize(1); - assertFilter(route.getFilters().get(0), type, order); + assertFilter(route.getFilters().get(0), type, expectedOrder); } private void assertFilter(GatewayFilter filter, Class type, int order) {