From 45d887f9733a1722d720e21ae6c8bf72fae29118 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 17 Jun 2025 17:19:21 +0200 Subject: [PATCH] Fix missing request body for GET and DELETE JdkClientHttpRequest This commit fixes a regression introduced in gh-34971 where GET and DELETE requests would not allow request bodies anymore for `JdkClientHttpRequest`. We are now using `builder.GET()` and `builder.DELETE()` methods only if the provided body is null. Fixes gh-35068 --- .../http/client/JdkClientHttpRequest.java | 48 +++++++++---------- .../JdkClientHttpRequestFactoryTests.java | 13 ++++- 2 files changed, 36 insertions(+), 25 deletions(-) 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 c8dd38f8eb3..e2955266ab3 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 @@ -149,38 +149,38 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest { } }); - switch (this.method.name()) { - case "GET" : - builder.GET(); - break; - case "DELETE" : - builder.DELETE(); - break; - default : - builder.method(this.method.name(), bodyPublisher(headers, body)); + if (body != null) { + builder.method(this.method.name(), bodyPublisher(headers, body)); + } + else { + switch (this.method.name()) { + case "GET" : + builder.GET(); + break; + case "DELETE" : + builder.DELETE(); + break; + default : + builder.method(this.method.name(), HttpRequest.BodyPublishers.noBody()); + } } return builder.build(); } - private HttpRequest.BodyPublisher bodyPublisher(HttpHeaders headers, @Nullable Body body) { - if (body != null) { - Flow.Publisher publisher = new OutputStreamPublisher<>( - os -> body.writeTo(StreamUtils.nonClosing(os)), BYTE_MAPPER, this.executor, null); + private HttpRequest.BodyPublisher bodyPublisher(HttpHeaders headers, Body body) { + Flow.Publisher publisher = new OutputStreamPublisher<>( + os -> body.writeTo(StreamUtils.nonClosing(os)), BYTE_MAPPER, this.executor, null); - long contentLength = headers.getContentLength(); - if (contentLength > 0) { - return HttpRequest.BodyPublishers.fromPublisher(publisher, contentLength); - } - else if (contentLength == 0) { - return HttpRequest.BodyPublishers.noBody(); - } - else { - return HttpRequest.BodyPublishers.fromPublisher(publisher); - } + long contentLength = headers.getContentLength(); + if (contentLength > 0) { + return HttpRequest.BodyPublishers.fromPublisher(publisher, contentLength); } - else { + else if (contentLength == 0) { return HttpRequest.BodyPublishers.noBody(); } + else { + return HttpRequest.BodyPublishers.fromPublisher(publisher); + } } /** diff --git a/spring-web/src/test/java/org/springframework/http/client/JdkClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/JdkClientHttpRequestFactoryTests.java index 6dca75adbb6..3ca3525f883 100644 --- a/spring-web/src/test/java/org/springframework/http/client/JdkClientHttpRequestFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/http/client/JdkClientHttpRequestFactoryTests.java @@ -93,10 +93,21 @@ class JdkClientHttpRequestFactoryTests extends AbstractHttpRequestFactoryTests { } } + @Test // gh-35068 + void deleteRequestWithBody() throws Exception { + URI uri = URI.create(baseUrl + "/echo"); + ClientHttpRequest request = this.factory.createRequest(uri, HttpMethod.DELETE); + StreamUtils.copy("body", StandardCharsets.ISO_8859_1, request.getBody()); + try (ClientHttpResponse response = request.execute()) { + assertThat(response.getStatusCode()).as("Invalid response status").isEqualTo(HttpStatus.OK); + assertThat(StreamUtils.copyToString(response.getBody(), StandardCharsets.ISO_8859_1)) + .as("Invalid request body").isEqualTo("body"); + } + } @Test // gh-34971 @EnabledForJreRange(min = JRE.JAVA_19) // behavior fixed in Java 19 - void requestContentLengthHeader() throws Exception { + void requestContentLengthHeaderWhenNoBody() throws Exception { URI uri = URI.create(baseUrl + "/header/Content-Length"); assertNoContentLength(uri, HttpMethod.GET); assertNoContentLength(uri, HttpMethod.DELETE);