From 57b8100a063e87886eaf67d5910f3ad94da63ac6 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Mon, 11 Dec 2023 12:57:09 +0100 Subject: [PATCH] Copy headers map in RestClientResponseException to ensure serializability This commit ensures that the HttpHeaders used are serializable by making a copy. Closes gh-31787 --- .../client/RestClientResponseException.java | 20 ++++++++++++++++++- .../DefaultResponseErrorHandlerTests.java | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java b/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java index 20974f96b039..e1a8a76333f8 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java @@ -27,6 +27,8 @@ import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; /** * Common base class for exceptions that contain actual HTTP response data. @@ -88,11 +90,27 @@ public RestClientResponseException( super(message); this.statusCode = statusCode; this.statusText = statusText; - this.responseHeaders = headers; + this.responseHeaders = copyHeaders(headers); this.responseBody = (responseBody != null ? responseBody : new byte[0]); this.responseCharset = (responseCharset != null ? responseCharset.name() : null); } + /** + * Copies the given headers, because the backing map might not be + * serializable. + */ + @Nullable + private static HttpHeaders copyHeaders(@Nullable HttpHeaders headers) { + if (headers != null) { + MultiValueMap result = new LinkedMultiValueMap<>(headers.size()); + headers.forEach((name, values) -> values.forEach(value -> result.add(name, value))); + return HttpHeaders.readOnlyHttpHeaders(result); + } + else { + return null; + } + } + /** * Return the HTTP status code. diff --git a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java index 43c9dfc2c783..1e713b4ab230 100644 --- a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java @@ -74,7 +74,7 @@ public void handleError() throws Exception { assertThatExceptionOfType(HttpClientErrorException.class) .isThrownBy(() -> handler.handleError(response)) .withMessage("404 Not Found: \"Hello World\"") - .satisfies(ex -> assertThat(ex.getResponseHeaders()).isSameAs(headers)); + .satisfies(ex -> assertThat(ex.getResponseHeaders()).isEqualTo(headers)); } @Test