DefaultResponseErrorHandler detects non-standard error code as well

Issue: SPR-17439
This commit is contained in:
Juergen Hoeller
2018-11-23 13:55:50 +01:00
parent b90553db5c
commit 738097def2
4 changed files with 122 additions and 33 deletions

View File

@@ -522,7 +522,6 @@ public enum HttpStatus {
return status;
}
/**
* Resolve the given status code to an {@code HttpStatus}, if possible.
* @param statusCode the HTTP status code (potentially non-standard)
@@ -565,18 +564,45 @@ public enum HttpStatus {
return this.value;
}
public static Series valueOf(int status) {
int seriesCode = status / 100;
/**
* Return the enum constant of this type with the corresponding series.
* @param status a standard HTTP status enum value
* @return the enum constant of this type with the corresponding series
* @throws IllegalArgumentException if this enum has no corresponding constant
*/
public static Series valueOf(HttpStatus status) {
return valueOf(status.value);
}
/**
* Return the enum constant of this type with the corresponding series.
* @param statusCode the HTTP status code (potentially non-standard)
* @return the enum constant of this type with the corresponding series
* @throws IllegalArgumentException if this enum has no corresponding constant
*/
public static Series valueOf(int statusCode) {
Series series = resolve(statusCode);
if (series == null) {
throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
}
return series;
}
/**
* Resolve the given status code to an {@code HttpStatus.Series}, if possible.
* @param statusCode the HTTP status code (potentially non-standard)
* @return the corresponding {@code Series}, or {@code null} if not found
* @since 5.1.3
*/
@Nullable
public static Series resolve(int statusCode) {
int seriesCode = statusCode / 100;
for (Series series : values()) {
if (series.value == seriesCode) {
return series;
}
}
throw new IllegalArgumentException("No matching constant for [" + status + "]");
}
public static Series valueOf(HttpStatus status) {
return valueOf(status.value);
return null;
}
}

View File

@@ -48,8 +48,9 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
*/
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
return (statusCode != null && hasError(statusCode));
int rawStatusCode = response.getRawStatusCode();
HttpStatus statusCode = HttpStatus.resolve(rawStatusCode);
return (statusCode != null ? hasError(statusCode) : hasError(rawStatusCode));
}
/**
@@ -58,7 +59,7 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
* {@code HttpStatus.Series#CLIENT_ERROR CLIENT_ERROR} or
* {@code HttpStatus.Series#SERVER_ERROR SERVER_ERROR}.
* Can be overridden in subclasses.
* @param statusCode the HTTP status code
* @param statusCode the HTTP status code as enum value
* @return {@code true} if the response has an error; {@code false} otherwise
*/
protected boolean hasError(HttpStatus statusCode) {
@@ -66,6 +67,21 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
statusCode.series() == HttpStatus.Series.SERVER_ERROR);
}
/**
* Template method called from {@link #hasError(ClientHttpResponse)}.
* <p>The default implementation checks if the given status code is
* {@code HttpStatus.Series#CLIENT_ERROR CLIENT_ERROR} or
* {@code HttpStatus.Series#SERVER_ERROR SERVER_ERROR}.
* Can be overridden in subclasses.
* @param unknownStatusCode the HTTP status code as raw value
* @return {@code true} if the response has an error; {@code false} otherwise
* @since 4.3.21
*/
protected boolean hasError(int unknownStatusCode) {
HttpStatus.Series series = HttpStatus.Series.resolve(unknownStatusCode);
return (series == HttpStatus.Series.CLIENT_ERROR || series == HttpStatus.Series.SERVER_ERROR);
}
/**
* Delegates to {@link #handleError(ClientHttpResponse, HttpStatus)} with the response status code.
*/

View File

@@ -28,7 +28,6 @@ import org.springframework.http.client.ClientHttpResponse;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import static org.mockito.Mockito.mock;
import static org.springframework.http.HttpStatus.*;
/**
@@ -66,7 +65,7 @@ public class DefaultResponseErrorHandlerHttpStatusTests {
public HttpStatus httpStatus;
@Parameterized.Parameter(1)
public Class expectedExceptionClass;
public Class<? extends Throwable> expectedExceptionClass;
private final DefaultResponseErrorHandler handler = new DefaultResponseErrorHandler();
@@ -74,7 +73,13 @@ public class DefaultResponseErrorHandlerHttpStatusTests {
@Test
public void handleErrorIOException() throws Exception {
public void hasErrorTrue() throws Exception {
given(this.response.getRawStatusCode()).willReturn(this.httpStatus.value());
assertTrue(this.handler.hasError(this.response));
}
@Test
public void handleErrorException() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
@@ -91,10 +96,4 @@ public class DefaultResponseErrorHandlerHttpStatusTests {
}
}
@Test
public void hasErrorTrue() throws Exception {
given(this.response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value());
assertTrue(handler.hasError(this.response));
}
}

View File

@@ -65,7 +65,7 @@ public class DefaultResponseErrorHandlerTests {
given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value());
given(response.getStatusText()).willReturn("Not Found");
given(response.getHeaders()).willReturn(headers);
given(response.getBody()).willReturn(new ByteArrayInputStream("Hello World".getBytes("UTF-8")));
given(response.getBody()).willReturn(new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)));
try {
handler.handleError(response);
@@ -101,18 +101,6 @@ public class DefaultResponseErrorHandlerTests {
handler.handleError(response);
}
@Test(expected = UnknownHttpStatusCodeException.class) // SPR-9406
public void unknownStatusCode() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
given(response.getRawStatusCode()).willReturn(999);
given(response.getStatusText()).willReturn("Custom status code");
given(response.getHeaders()).willReturn(headers);
handler.handleError(response);
}
@Test // SPR-16108
public void hasErrorForUnknownStatusCode() throws Exception {
HttpHeaders headers = new HttpHeaders();
@@ -125,6 +113,66 @@ public class DefaultResponseErrorHandlerTests {
assertFalse(handler.hasError(response));
}
@Test(expected = UnknownHttpStatusCodeException.class) // SPR-9406
public void handleErrorUnknownStatusCode() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
given(response.getRawStatusCode()).willReturn(999);
given(response.getStatusText()).willReturn("Custom status code");
given(response.getHeaders()).willReturn(headers);
handler.handleError(response);
}
@Test // SPR-17461
public void hasErrorForCustomClientError() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
given(response.getRawStatusCode()).willReturn(499);
given(response.getStatusText()).willReturn("Custom status code");
given(response.getHeaders()).willReturn(headers);
assertTrue(handler.hasError(response));
}
@Test(expected = UnknownHttpStatusCodeException.class)
public void handleErrorForCustomClientError() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
given(response.getRawStatusCode()).willReturn(499);
given(response.getStatusText()).willReturn("Custom status code");
given(response.getHeaders()).willReturn(headers);
handler.handleError(response);
}
@Test // SPR-17461
public void hasErrorForCustomServerError() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
given(response.getRawStatusCode()).willReturn(599);
given(response.getStatusText()).willReturn("Custom status code");
given(response.getHeaders()).willReturn(headers);
assertTrue(handler.hasError(response));
}
@Test(expected = UnknownHttpStatusCodeException.class)
public void handleErrorForCustomServerError() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
given(response.getRawStatusCode()).willReturn(599);
given(response.getStatusText()).willReturn("Custom status code");
given(response.getHeaders()).willReturn(headers);
handler.handleError(response);
}
@Test // SPR-16604
public void bodyAvailableAfterHasErrorForUnknownStatusCode() throws Exception {
HttpHeaders headers = new HttpHeaders();