Skip to content

Commit 3b3f27d

Browse files
committed
DefaultResponseErrorHandler.hasError avoids exception for unknown status
Issue: SPR-16604
1 parent f32b13c commit 3b3f27d

File tree

2 files changed

+71
-11
lines changed

2 files changed

+71
-11
lines changed

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,12 +47,13 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
4747
*/
4848
@Override
4949
public boolean hasError(ClientHttpResponse response) throws IOException {
50-
try {
51-
return hasError(getHttpStatusCode(response));
52-
}
53-
catch (UnknownHttpStatusCodeException ex) {
54-
return false;
50+
int rawStatusCode = response.getRawStatusCode();
51+
for (HttpStatus statusCode : HttpStatus.values()) {
52+
if (statusCode.value() == rawStatusCode) {
53+
return hasError(statusCode);
54+
}
5555
}
56+
return false;
5657
}
5758

5859
/**
@@ -87,13 +88,15 @@ public void handleError(ClientHttpResponse response) throws IOException {
8788
throw new HttpServerErrorException(statusCode, response.getStatusText(),
8889
response.getHeaders(), getResponseBody(response), getCharset(response));
8990
default:
90-
throw new RestClientException("Unknown status code [" + statusCode + "]");
91+
throw new UnknownHttpStatusCodeException(statusCode.value(), response.getStatusText(),
92+
response.getHeaders(), getResponseBody(response), getCharset(response));
9193
}
9294
}
9395

9496

9597
/**
9698
* Determine the HTTP status of the given response.
99+
* <p>Note: Only called from {@link #handleError}, not from {@link #hasError}.
97100
* @param response the response to inspect
98101
* @return the associated HTTP status
99102
* @throws IOException in case of I/O errors

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

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,13 +18,15 @@
1818

1919
import java.io.ByteArrayInputStream;
2020
import java.io.IOException;
21+
import java.nio.charset.Charset;
2122

2223
import org.junit.Test;
2324

2425
import org.springframework.http.HttpHeaders;
2526
import org.springframework.http.HttpStatus;
2627
import org.springframework.http.MediaType;
2728
import org.springframework.http.client.ClientHttpResponse;
29+
import org.springframework.util.StreamUtils;
2830

2931
import static org.junit.Assert.*;
3032
import static org.mockito.BDDMockito.*;
@@ -34,23 +36,26 @@
3436
*
3537
* @author Arjen Poutsma
3638
* @author Juergen Hoeller
39+
* @author Denys Ivano
3740
*/
3841
public class DefaultResponseErrorHandlerTests {
3942

43+
private final Charset UTF8 = Charset.forName("UTF-8");
44+
4045
private final DefaultResponseErrorHandler handler = new DefaultResponseErrorHandler();
4146

4247
private final ClientHttpResponse response = mock(ClientHttpResponse.class);
4348

4449

4550
@Test
4651
public void hasErrorTrue() throws Exception {
47-
given(response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND);
52+
given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value());
4853
assertTrue(handler.hasError(response));
4954
}
5055

5156
@Test
5257
public void hasErrorFalse() throws Exception {
53-
given(response.getStatusCode()).willReturn(HttpStatus.OK);
58+
given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value());
5459
assertFalse(handler.hasError(response));
5560
}
5661

@@ -115,11 +120,63 @@ public void hasErrorForUnknownStatusCode() throws Exception {
115120
HttpHeaders headers = new HttpHeaders();
116121
headers.setContentType(MediaType.TEXT_PLAIN);
117122

118-
given(response.getStatusCode()).willThrow(new IllegalArgumentException("No matching constant for 999"));
123+
given(response.getRawStatusCode()).willReturn(999);
124+
given(response.getStatusText()).willReturn("Custom status code");
125+
given(response.getHeaders()).willReturn(headers);
126+
127+
assertFalse(handler.hasError(response));
128+
}
129+
130+
@Test // SPR-16604
131+
public void bodyAvailableAfterHasErrorForUnknownStatusCode() throws Exception {
132+
HttpHeaders headers = new HttpHeaders();
133+
headers.setContentType(MediaType.TEXT_PLAIN);
134+
TestByteArrayInputStream body = new TestByteArrayInputStream("Hello World".getBytes("UTF-8"));
135+
136+
given(response.getRawStatusCode()).willReturn(999);
119137
given(response.getStatusText()).willReturn("Custom status code");
120138
given(response.getHeaders()).willReturn(headers);
139+
given(response.getBody()).willReturn(body);
121140

122141
assertFalse(handler.hasError(response));
142+
assertFalse(body.isClosed());
143+
assertEquals("Hello World", StreamUtils.copyToString(response.getBody(), UTF8));
144+
}
145+
146+
147+
private static class TestByteArrayInputStream extends ByteArrayInputStream {
148+
149+
private boolean closed;
150+
151+
public TestByteArrayInputStream(byte[] buf) {
152+
super(buf);
153+
this.closed = false;
154+
}
155+
156+
public boolean isClosed() {
157+
return closed;
158+
}
159+
160+
@Override
161+
public boolean markSupported() {
162+
return false;
163+
}
164+
165+
@Override
166+
public synchronized void mark(int readlimit) {
167+
throw new UnsupportedOperationException("mark/reset not supported");
168+
}
169+
170+
@Override
171+
public synchronized void reset() {
172+
throw new UnsupportedOperationException("mark/reset not supported");
173+
}
174+
175+
@Override
176+
public void close() throws IOException {
177+
super.close();
178+
this.closed = true;
179+
}
123180
}
124181

125182
}

0 commit comments

Comments
 (0)