In Spring Web 6.0.13, with Apache HttpClient configured to provide credentials, posting a MultiValueMap
to an endpoint protected using Digest Authentication works.
When Spring Web 6.1.0-RC2 is used, instead of responding to the authentication challenge, the 401 response is returned to the caller.
Demo repository: https://github.com/nwholloway/spring-web-bug
This contains a Docker Compose configuration to provide digest auth secured endpoint, and the demonstration Java code.
If you change the Spring Web version in build.gradle
from 6.1.0-RC2
to 6.0.13 the expected 200 response is received.
Comment From: snicoll
Thanks for the report and the sample. We believe that some recent work in that area may have contributed to this problem. We'll look into it ASAP.
Comment From: poutsma
This is related to #30557. For digest authentication to work, the request body has to be written multiple times, due to redirects. Prior to 6.1, all request bodies were buffered into a byte array, which can be written multiple times. As of 6.1, we no longer do so in order to save memory.
If you still want to buffer the request body, just like in 6.0, you can wrap the HttpComponentsClientHttpRequestFactory
in a BufferingClientHttpRequestFactory
, like so:
ClientHttpRequestFactory requestFactory = new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
return new RestTemplate(requestFactory);
Making the above change in Demo.java
in your demo app fixes the issue in Spring Framework 6.1.0-RC2. See also #31449, wherein changes were made to support repeatable writes.
However, I believe that buffering all requests is a bit excessive, and should not be necessary. In the case of your demo app, for instance, the request body consists of a MultiValueMap
which can safely be written to an output stream multiple times. Only read-once bodies, such as InputStream
objects, cannot be written multiple times.
So I will make some additional changes to the HttpMessageConverter
implementations and allow repeatable writes where it makes sense.
Comment From: poutsma
To be clear, with the changes made in 6dd93d4 that will be in 6.1.0, you should not have to wrap the request factory with a BufferingClientHttpRequestFactory
anymore.