Skip to content

Commit a7ffe09

Browse files
committed
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 (cherry picked from commit 8c30b8e)
1 parent 6407cb9 commit a7ffe09

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.web.reactive.function.server;
1818

19+
import java.util.Collections;
20+
import java.util.LinkedHashMap;
1921
import java.util.List;
2022
import java.util.Map;
2123
import java.util.function.Function;
@@ -439,12 +441,28 @@ public Mono<HandlerFunction<T>> route(ServerRequest serverRequest) {
439441
"Nested predicate \"%s\" matches against \"%s\"",
440442
this.predicate, serverRequest));
441443
}
442-
return this.routerFunction.route(nestedRequest);
444+
return this.routerFunction.route(nestedRequest)
445+
.doOnNext(match -> {
446+
mergeTemplateVariables(serverRequest, nestedRequest.pathVariables());
447+
});
443448
}
444449
)
445450
.orElseGet(Mono::empty);
446451
}
447452

453+
@SuppressWarnings("unchecked")
454+
private void mergeTemplateVariables(ServerRequest request, Map<String, String> variables) {
455+
if (!variables.isEmpty()) {
456+
Map<String, Object> attributes = request.attributes();
457+
Map<String, String> oldVariables = (Map<String, String>)request.attribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE)
458+
.orElseGet(LinkedHashMap::new);
459+
Map<String, String> mergedVariables = new LinkedHashMap<>(oldVariables);
460+
mergedVariables.putAll(variables);
461+
attributes.put(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE,
462+
Collections.unmodifiableMap(mergedVariables));
463+
}
464+
}
465+
448466
@Override
449467
public void accept(Visitor visitor) {
450468
visitor.startNested(this.predicate);

spring-webflux/src/test/java/org/springframework/web/reactive/function/server/NestedRouteIntegrationTests.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati
4141
protected RouterFunction<?> routerFunction() {
4242
NestedHandler nestedHandler = new NestedHandler();
4343
return nest(path("/foo/"),
44-
route(GET("/bar"), nestedHandler::bar)
45-
.andRoute(GET("/baz"), nestedHandler::baz))
46-
.andNest(GET("/{foo}"),
47-
nest(GET("/{bar}"),
48-
route(GET("/{baz}"), nestedHandler::variables)))
44+
route(GET("/bar"), nestedHandler::bar)
45+
.andRoute(GET("/baz"), nestedHandler::baz))
46+
.andNest(GET("/{foo}"),
47+
route(GET("/bar"), nestedHandler::variables).and(
48+
nest(GET("/{bar}"),
49+
route(GET("/{baz}"), nestedHandler::variables))))
4950
.andRoute(GET("/{qux}/quux"), nestedHandler::variables);
5051
}
5152

@@ -77,6 +78,17 @@ public void variables() throws Exception {
7778
assertEquals("{foo=1, bar=2, baz=3}", result.getBody());
7879
}
7980

81+
// SPR-16868
82+
@Test
83+
public void parentVariables() throws Exception {
84+
ResponseEntity<String> result =
85+
restTemplate.getForEntity("http://localhost:" + port + "/1/bar", String.class);
86+
87+
assertEquals(HttpStatus.OK, result.getStatusCode());
88+
assertEquals("{foo=1}", result.getBody());
89+
90+
}
91+
8092
// SPR 16692
8193
@Test
8294
public void removeFailedPathVariables() throws Exception {

0 commit comments

Comments
 (0)