Affects: 6.1.1

We have a generic HTTP client interceptor logic for logging http client request and response contents. In order to support different http client vendors, including Spring Rest Template, we have wrapper Request and Response classes just like Spring http client does for different vendors.

For Apache Http Components 5, we replace the request and response HttpEntity instances with wrappers that return the original content or a buffered version of the content depending on the circumstance. Our library works with Spring Boot versions 2.7.X to 3.2.0 ( using dependency-management plugin for default versions of http clients coming with spring boot)

With the latest changes here: https://github.com/spring-projects/spring-framework/blob/eeb145ee0b860b29cfc6109704305821fc9125b7/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java#L146 , our HttpEntity wrappers can't perform any logic based on the original content.

I believe this is a bug because it kind of breaks the contract of the HttpEntity. The interceptor works when a request is made directly through the HttpComponents API but it fails when it is sent through the RestTemplate that is using HttpComponents as the http client.

Wouldn't this change also break any native HttpComponents interceptor that replaces the request entity with a wrapper? The only way for the wrapper to get the contents is the wrapped entity's getContent() method

Comment From: injae-kim

https://github.com/spring-projects/spring-framework/commit/033bebf8cd4a2933788e1ea3540404aefdac2cf7 Remove buffering from ClientHttpRequest implementations

FYI) based on above PR, maybe this behavior is intended?

Comment From: ckalan

Even if the behavior is intended, doesn't it break the HttpEntity contract? An HttpComponents interceptor should be able to replace the HttpEntity with a wrapper which relies on the original one but this implementation prevents access to the original content and doesn't allow any workaround.

Comment From: snicoll

Even if the behavior is intended, doesn't it break the HttpEntity contract?

I don't think so. As @injae-kim hinted, this is intended to avoid streaming the content of the request in memory. If you're ok with the buffering bit, which definitely seem to be the case given the use case you've described, then you need to wrap your ClientHttpRequestFactory into a BufferingClientHttpRequestFactory as described in the upgrade guide.

If that doesn't help you, please share a small sample that reproduces the problem with the above applied and we can reopen this issue.

Comment From: ckalan

I checked again and you are right as HttpEntity.getContent may throw UnsupportedOperationException according to its contract, which we didn't notice. Thanks for checking this and the suggestion!