From 3afd5ce7dff4d7609dab1624e5dc8ac25ff6f978 Mon Sep 17 00:00:00 2001 From: Yash Siwach Date: Tue, 18 Aug 2026 23:28:11 +0530 Subject: [PATCH] Accept @Nullable contextPath in ServerHttpRequest.Builder Mark the contextPath parameter as @Nullable in both the ServerHttpRequest.Builder interface and DefaultServerHttpRequestBuilder implementation. Previously, although DefaultServerHttpRequestBuilder handled null values internally (e.g., in MutatedServerHttpRequest and DefaultRequestPath.initContextPath()), the public interface lacked the @Nullable annotation. In a @NullMarked package, this caused compile-time validation issues (such as under NullAway) for callers trying to pass null to reset/clear the context path. Closes gh-37098 Signed-off-by: Yash Siwach --- .../reactive/DefaultServerHttpRequestBuilder.java | 2 +- .../http/server/reactive/ServerHttpRequest.java | 5 ++++- .../reactive/DefaultServerHttpRequestBuilderTests.java | 10 ++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) 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 a09bc19e2d22..f316bc510544 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 @@ -103,7 +103,7 @@ public ServerHttpRequest.Builder path(String path) { } @Override - public ServerHttpRequest.Builder contextPath(String contextPath) { + public ServerHttpRequest.Builder contextPath(@Nullable String contextPath) { this.contextPath = contextPath; return this; } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpRequest.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpRequest.java index 420087a439fe..bc4dc4490294 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpRequest.java @@ -146,8 +146,11 @@ interface Builder { * contextPath} and it must match the start of the path of the URI of * the request. That means changing the contextPath, implies also * changing the path via {@link #path(String)}. + *

A {@code null} value is treated the same as an empty string and + * results in an empty context path. */ - Builder contextPath(String contextPath); + Builder contextPath(@Nullable String contextPath); + /** * Set or override the specified header values under the given name. diff --git a/spring-web/src/test/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilderTests.java b/spring-web/src/test/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilderTests.java index 32eef589dbd8..42c105b56ce4 100644 --- a/spring-web/src/test/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilderTests.java @@ -91,6 +91,15 @@ private ServerHttpRequest createMockRequest(HttpHeaders originalHeaders) { return mock; } + @org.junit.jupiter.api.Test + void contextPathNullable() { + ServerHttpRequest request = MockServerHttpRequest.get("/foo/bar").contextPath("/foo").build(); + assertThat(request.getPath().contextPath().value()).isEqualTo("/foo"); + + ServerHttpRequest mutated = request.mutate().contextPath(null).build(); + assertThat(mutated.getPath().contextPath().value()).isEmpty(); + } + static Arguments initHeader(String description, MultiValueMap headerMap) { headerMap.add("CaseInsensitive", "unmodified"); return argumentSet(description, headerMap, true); @@ -111,3 +120,4 @@ static Stream headers() { } } +