From d835fe311d20d5de103b8667d55592bf087be0f5 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 11 Dec 2025 09:40:42 +0100 Subject: [PATCH] Do not send null HTTP header value in JdkClientHttpRequest Prior to this commit, the `JdkClientHttpRequest` would add all values from `HttpHeaders` to the native request builder. This could cause `NullPointerException` being thrown at runtime because the `HttpClient` does not support that. This commit replicates a fix that was applied to the `SimpleClientHttpRequest`, turning null values into empty "". Fixes gh-35996 --- .../http/client/JdkClientHttpRequest.java | 2 +- .../client/RestClientIntegrationTests.java | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java index 2f8af19d93f..f743c472c1b 100644 --- a/spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java @@ -175,7 +175,7 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest { headers.forEach((headerName, headerValues) -> { if (!DISALLOWED_HEADERS.contains(headerName.toLowerCase(Locale.ROOT))) { for (String headerValue : headerValues) { - builder.header(headerName, headerValue); + builder.header(headerName, (headerValue != null) ? headerValue : ""); } } }); diff --git a/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java index e34c65e70bf..8d2192fb4d9 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestClientIntegrationTests.java @@ -1024,6 +1024,29 @@ class RestClientIntegrationTests { expectRequest(request -> assertThat(request.getHeaders().get("foo")).isEqualTo("bar")); } + + @ParameterizedRestClientTest + void sendNullHeaderValue(ClientHttpRequestFactory requestFactory) throws IOException { + startServer(requestFactory); + + prepareResponse(builder -> builder + .setHeader("Content-Type", "text/plain").body("Hello Spring!")); + + String result = this.restClient.get() + .uri("/greeting") + .httpRequest(request -> request.getHeaders().add("X-Test-Header", null)) + .retrieve() + .body(String.class); + + assertThat(result).isEqualTo("Hello Spring!"); + + expectRequestCount(1); + expectRequest(request -> { + assertThat(request.getHeaders().get("X-Test-Header")).isNullOrEmpty(); + assertThat(request.getTarget()).isEqualTo("/greeting"); + }); + } + @ParameterizedRestClientTest void defaultRequest(ClientHttpRequestFactory requestFactory) throws IOException { startServer(requestFactory);