diff --git a/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index 210f2717..85cc634e 100644 --- a/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -31,6 +31,7 @@ import org.springframework.cloud.gateway.filter.route.SetStatusRouteFilter; import org.springframework.cloud.gateway.handler.FilteringWebHandler; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; import org.springframework.cloud.gateway.handler.RoutingWebHandler; +import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicate; import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicate; import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicate; import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicate; @@ -119,6 +120,11 @@ public class GatewayAutoConfiguration { // Predicate beans + @Bean(name = "AfterRoutePredicate") + public AfterRoutePredicate afterRoutePredicate() { + return new AfterRoutePredicate(); + } + @Bean(name = "BeforeRoutePredicate") public BeforeRoutePredicate beforeRoutePredicate() { return new BeforeRoutePredicate(); diff --git a/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicate.java b/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicate.java new file mode 100644 index 00000000..f53a1d23 --- /dev/null +++ b/src/main/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicate.java @@ -0,0 +1,33 @@ +package org.springframework.cloud.gateway.handler.predicate; + +import java.time.ZonedDateTime; +import java.util.function.Predicate; + +import org.springframework.web.server.ServerWebExchange; + +/** + * @author Spencer Gibb + */ +public class AfterRoutePredicate implements RoutePredicate { + + @Override + public Predicate apply(String dateString, String[] args) { + //TODO: is ZonedDateTime the right thing to use? + try { + final long epoch = Long.parseLong(dateString); + + return exchange -> { + final long now = System.currentTimeMillis(); + return epoch >= now; + }; + } catch (NumberFormatException e) { + // try ZonedDateTime instead + final ZonedDateTime dateTime = ZonedDateTime.parse(dateString); + + return exchange -> { + final ZonedDateTime now = ZonedDateTime.now(); + return dateTime.isAfter(now); + }; + } + } +} diff --git a/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateTests.java b/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateTests.java new file mode 100644 index 00000000..27917415 --- /dev/null +++ b/src/test/java/org/springframework/cloud/gateway/handler/predicate/AfterRoutePredicateTests.java @@ -0,0 +1,59 @@ +package org.springframework.cloud.gateway.handler.predicate; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +import org.junit.Test; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.http.server.reactive.MockServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.adapter.DefaultServerWebExchange; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Spencer Gibb + */ +public class AfterRoutePredicateTests { + + @Test + public void beforeStringWorks() { + String dateString = ZonedDateTime.now().minusHours(1).format(DateTimeFormatter.ISO_ZONED_DATE_TIME); + + final boolean result = new AfterRoutePredicate().apply(dateString, null).test(getExchange()); + + assertThat(result).isFalse(); + } + + @Test + public void afterStringWorks() { + String dateString = ZonedDateTime.now().plusHours(1).format(DateTimeFormatter.ISO_ZONED_DATE_TIME); + + final boolean result = new AfterRoutePredicate().apply(dateString, null).test(getExchange()); + + assertThat(result).isTrue(); + } + + @Test + public void beforeEpochWorks() { + String dateString = String.valueOf(System.currentTimeMillis()-(1000*60*60)); + + final boolean result = new AfterRoutePredicate().apply(dateString, null).test(getExchange()); + + assertThat(result).isFalse(); + } + + @Test + public void afterEpochWorks() { + String dateString = String.valueOf(System.currentTimeMillis()+(1000*60*60)); + + final boolean result = new AfterRoutePredicate().apply(dateString, null).test(getExchange()); + + assertThat(result).isTrue(); + } + + private ServerWebExchange getExchange() { + final MockServerHttpRequest request = MockServerHttpRequest.get("http://example.com").build(); + return new DefaultServerWebExchange(request, new MockServerHttpResponse()); + } +}