Version: at least from 3.2.1 to 3.3.4 The issue occurs when using RestTemplate to call another server as a client. There is a specific use case doesn't work as expected: Steps to reproduce: 1. RestTemplate includes this line: restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory())); or an equivalent 2. Interceptor is created with a call getBody() on the result of ClientHttpRequestExecution.execute() inside of intercept() method override (for example, for logging purposes) 3. RestTemplate includes this interceptor 4. There is a call to restTemplate.exchange() with POST or PUT request, this request is expected to return an error (4xx or 5xx)

Expected result: getBody() for the result of ClientHttpRequestExecution.execute() inside of the interceptor override is succesfully processed and the execution proceeds as usual

Actual result: getBody() throws an IOException Error demonstration: https://github.com/Hotvianskyi/rest-remplate-bug

Comment From: wilkinsona

Thanks for the report and initial analysis but this isn't a Spring Boot problem as none of the code that's involved is part of Spring Boot. Spring Boot's code is all within the org.springframework.boot package space.

When your interceptor calls response.getBody(), there's no exception handling. This is unlike Framework's DefaultResponseErrorHandler which maps an IOException to an empty body:

protected byte[] getResponseBody(ClientHttpResponse response) {
    try {
        return FileCopyUtils.copyToByteArray(response.getBody());
    }
    catch (IOException ex) {
        // ignore
    }
    return new byte[0];
}

You could improve your interceptor by including similar logic to handle the exception thrown by the JDK's HttpURLConnection when an attempt is made to get the body of the 401 response:

    private static class LoggingInterceptor implements ClientHttpRequestInterceptor {

        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            var response = execution.execute(request, body);
            log.info(bodyToString(response));
            log.info(response.getStatusCode().toString());
            return response;
        }

        private String bodyToString(ClientHttpResponse response) throws IOException {
            StringBuilder builder = new StringBuilder();
            try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), StandardCharsets.UTF_8))) {
                String line = bufferedReader.readLine();
                while (line != null) {
                    builder.append(line).append(System.lineSeparator());
                    line = bufferedReader.readLine();
                }
            }
            catch (IOException ex) {
                // Treat body as empty as DefaultErrorResponseHandler does
            }
            return "Logged body:" + builder;
        }
    }

If you have any further questions, please follow up on Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.