From c4326cb0f5673b6e0e8dae912a0cb35a47916551 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Mon, 22 Jun 2020 19:13:10 +0200 Subject: [PATCH] Fix missing contextPath when mutating ServerHttpRequest This commit ensures that when mutating `ServerHttpRequest` instances, the original contextPath information is copied to the request being built. Note that mutation on the `contextPath(String)` or `path(String)` should be reflected to the other. (See their Javadoc for more information). Fixes gh-25279 --- .../DefaultServerHttpRequestBuilder.java | 1 + .../reactive/ServerHttpRequestTests.java | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilder.java b/spring-web/src/main/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilder.java index bc05a9da1a84..3ecb3bb0e09b 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilder.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilder.java @@ -71,6 +71,7 @@ public DefaultServerHttpRequestBuilder(ServerHttpRequest original) { this.uri = original.getURI(); this.httpMethodValue = original.getMethodValue(); + this.contextPath = original.getPath().contextPath().value(); this.body = original.getBody(); this.httpHeaders = HttpHeaders.writableHttpHeaders(original.getHeaders()); diff --git a/spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java b/spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java index c6917031bc0c..df71a36f7ac0 100644 --- a/spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java +++ b/spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java @@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; /** @@ -163,14 +164,42 @@ public void mutateHeaderBySettingHeaderValues() throws Exception { assertThat(request.getHeaders().get(headerName)).containsExactly(headerValue3); } + @Test + void mutateWithExistingContextPath() throws Exception { + ServerHttpRequest request = createHttpRequest("/context/path", "/context"); + + ServerHttpRequest mutated = request.mutate().build(); + assertThat(mutated.getPath().contextPath().value()).isEqualTo("/context"); + assertThat(mutated.getPath().pathWithinApplication().value()).isEqualTo("/path"); + assertThat(mutated.getURI().getRawPath()).isEqualTo("/context/path"); + + mutated = request.mutate().contextPath("/other").path("/other/path").build(); + assertThat(mutated.getPath().contextPath().value()).isEqualTo("/other"); + assertThat(mutated.getPath().pathWithinApplication().value()).isEqualTo("/path"); + assertThat(mutated.getURI().getRawPath()).isEqualTo("/other/path"); + } + + @Test + void mutateContextPathWithoutUpdatingPathShouldFail() throws Exception { + ServerHttpRequest request = createHttpRequest("/context/path", "/context"); + + assertThatThrownBy(() -> request.mutate().path("/fail").build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Invalid contextPath '/context': must match the start of requestPath: '/fail'"); + } + private ServerHttpRequest createHttpRequest(String uriString) throws Exception { + return createHttpRequest(uriString, ""); + } + + private ServerHttpRequest createHttpRequest(String uriString, String contextPath) throws Exception { URI uri = URI.create(uriString); MockHttpServletRequest request = new TestHttpServletRequest(uri); + request.setContextPath(contextPath); AsyncContext asyncContext = new MockAsyncContext(request, new MockHttpServletResponse()); return new ServletServerHttpRequest(request, asyncContext, "", new DefaultDataBufferFactory(), 1024); } - private static class TestHttpServletRequest extends MockHttpServletRequest { TestHttpServletRequest(URI uri) {