diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java index c8cdda69601..92f65245e75 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -349,6 +350,11 @@ public abstract class RequestPredicates { } } + private static void restoreAttributes(ServerRequest request, Map attributes) { + request.attributes().clear(); + request.attributes().putAll(attributes); + } + private static class HttpMethodPredicate implements RequestPredicate { @@ -518,8 +524,14 @@ public abstract class RequestPredicates { } @Override - public boolean test(ServerRequest t) { - return (this.left.test(t) && this.right.test(t)); + public boolean test(ServerRequest request) { + Map oldAttributes = new HashMap<>(request.attributes()); + + if (this.left.test(request) && this.right.test(request)) { + return true; + } + restoreAttributes(request, oldAttributes); + return false; } @Override @@ -533,7 +545,6 @@ public abstract class RequestPredicates { } } - /** * {@link RequestPredicate} for where either {@code left} or {@code right} predicates * may match. @@ -552,8 +563,20 @@ public abstract class RequestPredicates { } @Override - public boolean test(ServerRequest t) { - return (this.left.test(t) || this.right.test(t)); + public boolean test(ServerRequest request) { + Map oldAttributes = new HashMap<>(request.attributes()); + + if (this.left.test(request)) { + return true; + } + else { + restoreAttributes(request, oldAttributes); + if (this.right.test(request)) { + return true; + } + } + restoreAttributes(request, oldAttributes); + return false; } @Override diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/NestedRouteIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/NestedRouteIntegrationTests.java index 6153373617a..dbdb7293609 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/NestedRouteIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/NestedRouteIntegrationTests.java @@ -16,16 +16,23 @@ package org.springframework.web.reactive.function.server; +import java.util.Map; + import org.junit.Test; import reactor.core.publisher.Mono; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.*; -import static org.springframework.web.reactive.function.server.RequestPredicates.*; -import static org.springframework.web.reactive.function.server.RouterFunctions.*; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.all; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.nest; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; /** * @author Arjen Poutsma @@ -45,7 +52,8 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati route(GET("/bar"), nestedHandler::variables).and( nest(GET("/{bar}"), route(GET("/{baz}"), nestedHandler::variables)))) - .andRoute(GET("/{qux}/quux"), nestedHandler::variables); + .andRoute(path("/{qux}/quux").and(method(HttpMethod.GET)), nestedHandler::variables) + .andRoute(all(), nestedHandler::variables); } @@ -89,7 +97,7 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati // SPR 16692 @Test - public void removeFailedPathVariables() { + public void removeFailedNestedPathVariables() { ResponseEntity result = restTemplate.getForEntity("http://localhost:" + port + "/qux/quux", String.class); @@ -98,6 +106,17 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati } + // SPR 17210 + @Test + public void removeFailedPathVariablesAnd() { + ResponseEntity result = + restTemplate.postForEntity("http://localhost:" + port + "/qux/quux", "", String.class); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("{}", result.getBody()); + + } + private static class NestedHandler { @@ -109,11 +128,15 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati return ServerResponse.ok().syncBody("baz"); } + @SuppressWarnings("unchecked") public Mono variables(ServerRequest request) { - assertEquals(request.pathVariables(), - request.attributes().get(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE)); + Map pathVariables = request.pathVariables(); + Map attributePathVariables = + (Map) request.attributes().get(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + assertTrue( (pathVariables.equals(attributePathVariables)) + || (pathVariables.isEmpty() && (attributePathVariables == null))); - Mono responseBody = Mono.just(request.pathVariables().toString()); + Mono responseBody = Mono.just(pathVariables.toString()); return ServerResponse.ok().body(responseBody, String.class); }