Closed uli-f closed 6 months ago
Without knowing how you've created the RestTemplate
, it's hard to offer any suggestions. I suspect the difference may be because the underlying ClientHttpRequestFactory
is different or is behaving differently but that's only an educated guess at this point.
If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.
Thanks for the feedback. I will compile a sample that is able to reproduce the problem.
I put together a complete yet minimal sample that reproduces the problem:
The class com.example.PredictionController
provides an endpoint /result
; hitting this endpoint /result
kicks off the multipart/form-data POST
.
Here is what I experience on my end:
id "org.springframework.boot" version "3.1.9"
in build.gradle
) my other microservice at "http://prediction-service:5010/predict" understands the request just fine and responds as expectedid "org.springframework.boot" version "3.2.2"
in build.gradle
) my other microservice at "http://prediction-service:5010/predict" logs an error: /predict error BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
I'd appreciate any help on this.
Thanks. While the sample doesn't reproduce the problem as we don't have access to your other microservice, it did give me enough information to identify the cause of the problem.
The key difference here is that with Spring Boot 3.2.x the request is sent using chunked transfer encoding and with Spring Boot 3.1.x it is not. This is due to this change in Spring Framework 6.1 upon which Spring Boot 3.2 depends. It affects SimpleClientHttpRequestFactory
which you're using. I'm not sure what options are available to you to avoid Spring Framework 6.1 sending a chunked request. We'll transfer this issue to the Framework team for their attention.
Thank you for your looking into this, much appreciated.
The key difference here is that with Spring Boot 3.2.x, the request is sent using chunked transfer encoding and with Spring Boot 3.1.x it is not.
That's what I spotted as the only difference on the receiver's end when looking at the headers.
Looking forward to hearing from the Framework team.
From the upgrade guide:
To reduce memory usage in
RestClient
andRestTemplate
, mostClientHttpRequestFactory
implementations no longer buffer request bodies before sending them to the server. As a result, for certain content types such as JSON, the contents size is no longer known, and aContent-Length
header is no longer set. If you would like to buffer request bodies like before, simply wrap theClientHttpRequestFactory
you are using in aBufferingClientHttpRequestFactory
.
Please let us know if following the above instructions solves you issue.
I wrapped the ClientHttpRequestFactory
in a BufferingClientHttpRequestFactory
in my Bean restTemplate
:
@Bean
@Autowired
public RestTemplate restTemplate(RestTemplateBuilder builder) {
ClientHttpRequestFactory requestFactory = builder.buildRequestFactory();
builder = builder.requestFactory(() -> new BufferingClientHttpRequestFactory(requestFactory));
return builder.build();
}
With this change the Python flask service at the receiving end happily understands the request from Spring Boot 3.2.3. ✔️
Thank you @wilkinsona and @poutsma. This was one of the best support experiences I ever had in my life: quick, straight to the point and solved after one round of back and forth 😃
I experience an issue with
restTemplate.postForEntity(String,Object,Class<T>)
with Object of typeMultiValueMap<String,Object>
.Here is a code snippet to demonstrate what I am doing:
with
On the receiving end of this POST request sits a Python flask service.
When using Spring Boot 3.1.9 the request can be understood by the receiver. However, when switching to Spring Boot 3.2.2 the receiver does not understand the request anymore, that is, it is unable to receive the data of the
multipart/form-data
.Looking at the logging output of the receiver, the only difference I can spot is the header
Transfer-Encoding: chunked
that is only present in the request when using Spring Boot 3.2.2. However, it is not present in the logging output of the sender as logged by theCustomClientHttpRequestInterceptor
.As I haven't changed anything else, however, it seems to me that the update from Spring Boot 3.1.9 to Spring Boot 3.2.2 causes the client to not being able to understand the request anymore.
Details of the request can be found below.
POST request send with Spring Boot 3.1.9
Logging the request with a
CustomClientHttpRequestInterceptor
:Logging the the request on the receiving end:
POST request send with Spring Boot 3.2.2
Logging the request with a
CustomClientHttpRequestInterceptor
:Logging the the request on the receiving end: