Skip to content

Commit c4326cb

Browse files
committed
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
1 parent 80d1aae commit c4326cb

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

spring-web/src/main/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public DefaultServerHttpRequestBuilder(ServerHttpRequest original) {
7171

7272
this.uri = original.getURI();
7373
this.httpMethodValue = original.getMethodValue();
74+
this.contextPath = original.getPath().contextPath().value();
7475
this.body = original.getBody();
7576

7677
this.httpHeaders = HttpHeaders.writableHttpHeaders(original.getHeaders());

spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import static org.assertj.core.api.Assertions.assertThat;
3939
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
40+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4041
import static org.mockito.Mockito.mock;
4142

4243
/**
@@ -163,14 +164,42 @@ public void mutateHeaderBySettingHeaderValues() throws Exception {
163164
assertThat(request.getHeaders().get(headerName)).containsExactly(headerValue3);
164165
}
165166

167+
@Test
168+
void mutateWithExistingContextPath() throws Exception {
169+
ServerHttpRequest request = createHttpRequest("/context/path", "/context");
170+
171+
ServerHttpRequest mutated = request.mutate().build();
172+
assertThat(mutated.getPath().contextPath().value()).isEqualTo("/context");
173+
assertThat(mutated.getPath().pathWithinApplication().value()).isEqualTo("/path");
174+
assertThat(mutated.getURI().getRawPath()).isEqualTo("/context/path");
175+
176+
mutated = request.mutate().contextPath("/other").path("/other/path").build();
177+
assertThat(mutated.getPath().contextPath().value()).isEqualTo("/other");
178+
assertThat(mutated.getPath().pathWithinApplication().value()).isEqualTo("/path");
179+
assertThat(mutated.getURI().getRawPath()).isEqualTo("/other/path");
180+
}
181+
182+
@Test
183+
void mutateContextPathWithoutUpdatingPathShouldFail() throws Exception {
184+
ServerHttpRequest request = createHttpRequest("/context/path", "/context");
185+
186+
assertThatThrownBy(() -> request.mutate().path("/fail").build())
187+
.isInstanceOf(IllegalArgumentException.class)
188+
.hasMessage("Invalid contextPath '/context': must match the start of requestPath: '/fail'");
189+
}
190+
166191
private ServerHttpRequest createHttpRequest(String uriString) throws Exception {
192+
return createHttpRequest(uriString, "");
193+
}
194+
195+
private ServerHttpRequest createHttpRequest(String uriString, String contextPath) throws Exception {
167196
URI uri = URI.create(uriString);
168197
MockHttpServletRequest request = new TestHttpServletRequest(uri);
198+
request.setContextPath(contextPath);
169199
AsyncContext asyncContext = new MockAsyncContext(request, new MockHttpServletResponse());
170200
return new ServletServerHttpRequest(request, asyncContext, "", new DefaultDataBufferFactory(), 1024);
171201
}
172202

173-
174203
private static class TestHttpServletRequest extends MockHttpServletRequest {
175204

176205
TestHttpServletRequest(URI uri) {

0 commit comments

Comments
 (0)