Fix parent path variables in nested route functions

This commit fix an issue where path variables in a nested parent
RouterFunction were not committed to the request attributes.

Issue: SPR-16868
This commit is contained in:
Arjen Poutsma 2018-05-29 15:39:40 +02:00
parent e57d8e1e60
commit 8c30b8e628
2 changed files with 36 additions and 6 deletions

View File

@ -16,6 +16,8 @@
package org.springframework.web.reactive.function.server;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@ -460,12 +462,28 @@ public abstract class RouterFunctions {
"Nested predicate \"%s\" matches against \"%s\"",
this.predicate, serverRequest));
}
return this.routerFunction.route(nestedRequest);
return this.routerFunction.route(nestedRequest)
.doOnNext(match -> {
mergeTemplateVariables(serverRequest, nestedRequest.pathVariables());
});
}
)
.orElseGet(Mono::empty);
}
@SuppressWarnings("unchecked")
private void mergeTemplateVariables(ServerRequest request, Map<String, String> variables) {
if (!variables.isEmpty()) {
Map<String, Object> attributes = request.attributes();
Map<String, String> oldVariables = (Map<String, String>)request.attribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE)
.orElseGet(LinkedHashMap::new);
Map<String, String> mergedVariables = new LinkedHashMap<>(oldVariables);
mergedVariables.putAll(variables);
attributes.put(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE,
Collections.unmodifiableMap(mergedVariables));
}
}
@Override
public void accept(Visitor visitor) {
visitor.startNested(this.predicate);

View File

@ -44,8 +44,9 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati
route(GET("/bar"), nestedHandler::bar)
.andRoute(GET("/baz"), nestedHandler::baz))
.andNest(GET("/{foo}"),
route(GET("/bar"), nestedHandler::variables).and(
nest(GET("/{bar}"),
route(GET("/{baz}"), nestedHandler::variables)))
route(GET("/{baz}"), nestedHandler::variables))))
.andRoute(GET("/{qux}/quux"), nestedHandler::variables);
}
@ -77,6 +78,17 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati
assertEquals("{foo=1, bar=2, baz=3}", result.getBody());
}
// SPR-16868
@Test
public void parentVariables() throws Exception {
ResponseEntity<String> result =
restTemplate.getForEntity("http://localhost:" + port + "/1/bar", String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("{foo=1}", result.getBody());
}
// SPR 16692
@Test
public void removeFailedPathVariables() throws Exception {