Skip to content

Commit 2fb13d4

Browse files
awoodburysbrannen
authored andcommitted
Include response body in UnknownHttpStatusCodeException
Spring Framework 5.2.2 introduced a regression in DefaultResponseErrorHandler.handleError(ClientHttpResponse) Specifically, for use cases where the InputStream had already been consumed by the first invocation of getResponseBody(), the second invocation of getResponseBody() resulted in the response body being absent in the created UnknownHttpStatusCodeException. This commit fixes this by invoking getResponseBody() only once in DefaultResponseErrorHandler.handleError(ClientHttpReponse) in order to reuse the retrieved response body for creating the exception message and as a separate argument to the UnknownHttpStatusCodeException constructor. Closes gh-24595
1 parent 5e1e689 commit 2fb13d4

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,13 @@ protected boolean hasError(int unknownStatusCode) {
102102
public void handleError(ClientHttpResponse response) throws IOException {
103103
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
104104
if (statusCode == null) {
105+
byte[] body = getResponseBody(response);
105106
String message = getErrorMessage(
106107
response.getRawStatusCode(), response.getStatusText(),
107-
getResponseBody(response), getCharset(response));
108+
body, getCharset(response));
108109
throw new UnknownHttpStatusCodeException(message,
109110
response.getRawStatusCode(), response.getStatusText(),
110-
response.getHeaders(), getResponseBody(response), getCharset(response));
111+
response.getHeaders(), body, getCharset(response));
111112
}
112113
handleError(response, statusCode);
113114
}

spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import static org.assertj.core.api.Assertions.assertThat;
3434
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
35+
import static org.assertj.core.api.Assertions.catchThrowable;
3536
import static org.mockito.BDDMockito.given;
3637
import static org.mockito.Mockito.mock;
3738

@@ -160,15 +161,29 @@ public void hasErrorForCustomClientError() throws Exception {
160161

161162
@Test
162163
public void handleErrorForCustomClientError() throws Exception {
164+
int statusCode = 499;
165+
String statusText = "Custom status code";
166+
163167
HttpHeaders headers = new HttpHeaders();
164168
headers.setContentType(MediaType.TEXT_PLAIN);
165169

166-
given(response.getRawStatusCode()).willReturn(499);
167-
given(response.getStatusText()).willReturn("Custom status code");
170+
String responseBody = "Hello World";
171+
TestByteArrayInputStream body = new TestByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8));
172+
173+
given(response.getRawStatusCode()).willReturn(statusCode);
174+
given(response.getStatusText()).willReturn(statusText);
168175
given(response.getHeaders()).willReturn(headers);
176+
given(response.getBody()).willReturn(body);
169177

170-
assertThatExceptionOfType(UnknownHttpStatusCodeException.class).isThrownBy(() ->
171-
handler.handleError(response));
178+
Throwable throwable = catchThrowable(() -> handler.handleError(response));
179+
180+
// validate exception
181+
assertThat(throwable).isInstanceOf(UnknownHttpStatusCodeException.class);
182+
UnknownHttpStatusCodeException actualUnknownHttpStatusCodeException = (UnknownHttpStatusCodeException) throwable;
183+
assertThat(actualUnknownHttpStatusCodeException.getRawStatusCode()).isEqualTo(statusCode);
184+
assertThat(actualUnknownHttpStatusCodeException.getStatusText()).isEqualTo(statusText);
185+
assertThat(actualUnknownHttpStatusCodeException.getResponseHeaders()).isEqualTo(headers);
186+
assertThat(actualUnknownHttpStatusCodeException.getResponseBodyAsString()).isEqualTo(responseBody);
172187
}
173188

174189
@Test // SPR-17461
@@ -185,15 +200,29 @@ public void hasErrorForCustomServerError() throws Exception {
185200

186201
@Test
187202
public void handleErrorForCustomServerError() throws Exception {
203+
int statusCode = 599;
204+
String statusText = "Custom status code";
205+
188206
HttpHeaders headers = new HttpHeaders();
189207
headers.setContentType(MediaType.TEXT_PLAIN);
190208

191-
given(response.getRawStatusCode()).willReturn(599);
192-
given(response.getStatusText()).willReturn("Custom status code");
209+
String responseBody = "Hello World";
210+
TestByteArrayInputStream body = new TestByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8));
211+
212+
given(response.getRawStatusCode()).willReturn(statusCode);
213+
given(response.getStatusText()).willReturn(statusText);
193214
given(response.getHeaders()).willReturn(headers);
215+
given(response.getBody()).willReturn(body);
194216

195-
assertThatExceptionOfType(UnknownHttpStatusCodeException.class).isThrownBy(() ->
196-
handler.handleError(response));
217+
Throwable throwable = catchThrowable(() -> handler.handleError(response));
218+
219+
// validate exception
220+
assertThat(throwable).isInstanceOf(UnknownHttpStatusCodeException.class);
221+
UnknownHttpStatusCodeException actualUnknownHttpStatusCodeException = (UnknownHttpStatusCodeException) throwable;
222+
assertThat(actualUnknownHttpStatusCodeException.getRawStatusCode()).isEqualTo(statusCode);
223+
assertThat(actualUnknownHttpStatusCodeException.getStatusText()).isEqualTo(statusText);
224+
assertThat(actualUnknownHttpStatusCodeException.getResponseHeaders()).isEqualTo(headers);
225+
assertThat(actualUnknownHttpStatusCodeException.getResponseBodyAsString()).isEqualTo(responseBody);
197226
}
198227

199228
@Test // SPR-16604
@@ -212,7 +241,6 @@ public void bodyAvailableAfterHasErrorForUnknownStatusCode() throws Exception {
212241
assertThat(StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8)).isEqualTo("Hello World");
213242
}
214243

215-
216244
private static class TestByteArrayInputStream extends ByteArrayInputStream {
217245

218246
private boolean closed;

0 commit comments

Comments
 (0)