From f06edbaf1984610805ead5a7c6b70ddc3d9a9366 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 12 Dec 2018 18:24:19 -0500 Subject: [PATCH] Restores ability to just check for the presence of a header. fixes gh-715 --- .../HeaderRoutePredicateFactory.java | 23 ++++++++----- .../HeaderRoutePredicateFactoryTests.java | 32 ++++++++++++++++++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java index 7ee02f4a..e744ad56 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactory.java @@ -18,11 +18,13 @@ package org.springframework.cloud.gateway.handler.predicate; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.function.Predicate; import javax.validation.constraints.NotEmpty; +import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.server.ServerWebExchange; @@ -45,16 +47,21 @@ public class HeaderRoutePredicateFactory extends AbstractRoutePredicateFactory apply(Config config) { + boolean hasRegex = !StringUtils.isEmpty(config.regexp); + return exchange -> { - List values = exchange.getRequest().getHeaders().get(config.header); - if (values != null) { - for (String value : values) { - if (value.matches(config.regexp)) { - return true; - } - } + List values = exchange.getRequest().getHeaders().getOrDefault(config.header, Collections.emptyList()); + if (values.isEmpty()) { + return false; } - 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; }; } diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java index 05a746d5..a4a1f18d 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/handler/predicate/HeaderRoutePredicateFactoryTests.java @@ -19,11 +19,15 @@ package org.springframework.cloud.gateway.handler.predicate; import org.junit.Test; import org.junit.runner.RunWith; +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.RoutePredicateHandlerMapping; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; @@ -60,9 +64,35 @@ public class HeaderRoutePredicateFactoryTests extends BaseWebClientTests { .expectHeader().valueEquals(ROUTE_ID_HEADER, "default_path_to_httpbin"); } + @Test + public void headerExistsWorksWithDsl() { + testClient.get() + .uri("/get") + .header("X-Foo", "bar") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HANDLER_MAPPER_HEADER, + RoutePredicateHandlerMapping.class.getSimpleName()) + .expectHeader().valueEquals(ROUTE_ID_HEADER, "header_exists_dsl"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) - public static class TestConfig { } + public static class TestConfig { + + @Value("${test.uri}") + private String uri; + + @Bean + RouteLocator queryRouteLocator(RouteLocatorBuilder builder) { + return builder.routes() + .route("header_exists_dsl", r -> + r.header("X-Foo") + .filters(f -> f.prefixPath("/httpbin")) + .uri(uri)) + .build(); + } + } }