From 97cd9dd03ba57b0e8094a4290d4cda95878a7a9b Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 6 Jan 2026 16:56:45 +0100 Subject: [PATCH] Support HttpComponents 5.6 This commit updates the HttpComponents HttpClient to refer to the parsed `HttpEntity` for the content-related HTTP response headers such as encoding and body length. Closes gh-36100 --- framework-platform/framework-platform.gradle | 4 ++-- .../HttpComponentsClientHttpResponse.java | 10 ++++++++++ ...mponentsClientHttpRequestFactoryTests.java | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/framework-platform/framework-platform.gradle b/framework-platform/framework-platform.gradle index cdf8968181b..13ff9ac32f0 100644 --- a/framework-platform/framework-platform.gradle +++ b/framework-platform/framework-platform.gradle @@ -94,8 +94,8 @@ dependencies { api("org.apache.derby:derby:10.16.1.1") api("org.apache.derby:derbyclient:10.16.1.1") api("org.apache.derby:derbytools:10.16.1.1") - api("org.apache.httpcomponents.client5:httpclient5:5.5") - api("org.apache.httpcomponents.core5:httpcore5-reactive:5.3.5") + api("org.apache.httpcomponents.client5:httpclient5:5.6") + api("org.apache.httpcomponents.core5:httpcore5-reactive:5.4") api("org.apache.poi:poi-ooxml:5.2.5") api("org.apache.tomcat.embed:tomcat-embed-core:11.0.15") api("org.apache.tomcat.embed:tomcat-embed-websocket:11.0.15") diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java index abe2b0712f5..824ee3d8f0f 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java @@ -66,6 +66,16 @@ final class HttpComponentsClientHttpResponse implements ClientHttpResponse { public HttpHeaders getHeaders() { if (this.headers == null) { MultiValueMap adapter = new HttpComponentsHeadersAdapter(this.httpResponse); + // update headers if response is decompressed + HttpEntity httpEntity = this.httpResponse.getEntity(); + if (httpEntity != null) { + if (httpEntity.getContentLength() == -1) { + adapter.remove(HttpHeaders.CONTENT_LENGTH); + } + if (httpEntity.getContentEncoding() == null) { + adapter.remove(HttpHeaders.CONTENT_ENCODING); + } + } this.headers = HttpHeaders.readOnlyHttpHeaders(adapter); } return this.headers; diff --git a/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java index 77acae22b18..f9c2c59d256 100644 --- a/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactoryTests.java @@ -18,6 +18,7 @@ package org.springframework.http.client; import java.io.InputStreamReader; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.stream.Stream; @@ -32,9 +33,11 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.util.FileCopyUtils; +import org.springframework.util.StreamUtils; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.assertj.core.api.Assertions.assertThat; @@ -60,6 +63,22 @@ class HttpComponentsClientHttpRequestFactoryTests extends AbstractHttpRequestFac assertHttpMethod("patch", HttpMethod.PATCH); } + @Test + void shouldDecompressWithExpectedHeaders() throws Exception { + ClientHttpRequest request = factory.createRequest(URI.create(baseUrl + "/compress/gzip"), HttpMethod.POST); + String message = "Hello World"; + final byte[] body = message.getBytes(StandardCharsets.UTF_8); + StreamUtils.copy(body, request.getBody()); + + try (ClientHttpResponse response = request.execute()) { + assertThat(response.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.OK); + String result = FileCopyUtils.copyToString(new InputStreamReader(response.getBody())); + assertThat(result).as("Invalid body").isEqualTo(message); + assertThat(response.getHeaders().get(HttpHeaders.CONTENT_ENCODING)).isNull(); + assertThat(response.getHeaders().getContentLength()).isEqualTo(-1); + } + } + @Test void assertCustomConfig() throws Exception { HttpClient httpClient = HttpClientBuilder.create().build();