Skip to content

Commit

Permalink
Fix parent path variables in nested route functions
Browse files Browse the repository at this point in the history
This commit fix an issue where path variables in a nested parent
RouterFunction were not committed to the request attributes.

Issue: SPR-16868
  • Loading branch information
poutsma committed May 29, 2018
1 parent e57d8e1 commit 8c30b8e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -460,12 +462,28 @@ public Mono<HandlerFunction<T>> route(ServerRequest serverRequest) {
"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);
Expand Down
Expand Up @@ -41,11 +41,12 @@ public class NestedRouteIntegrationTests extends AbstractRouterFunctionIntegrati
protected RouterFunction<?> routerFunction() {
NestedHandler nestedHandler = new NestedHandler();
return nest(path("/foo/"),
route(GET("/bar"), nestedHandler::bar)
.andRoute(GET("/baz"), nestedHandler::baz))
.andNest(GET("/{foo}"),
nest(GET("/{bar}"),
route(GET("/{baz}"), nestedHandler::variables)))
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))))
.andRoute(GET("/{qux}/quux"), nestedHandler::variables);
}

Expand Down Expand Up @@ -77,6 +78,17 @@ public void variables() throws Exception {
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 {
Expand Down

0 comments on commit 8c30b8e

Please sign in to comment.