Skip to content

Commit 24c30ea

Browse files
committed
Raise RestClientException for unknown status codes
HttpStatus cannot be created with an unknown status code. If a server returns a status code that's not in the HttpStatus enum values, an IllegalArgumentException is raised. Rather than allowing it to propagate as such, this change ensures the actual exception raised is a RestClientException. Issue: SPR-9406 Backport-Issue: SPR-9502
1 parent 1af7575 commit 24c30ea

File tree

6 files changed

+175
-72
lines changed

6 files changed

+175
-72
lines changed

build-spring-framework/resources/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Changes in version 3.1.2 (2012-06-??)
1919
* add Jackson 2 HttpMessageConverter and View types
2020
* translate IOException from Jackson to HttpMessageNotReadableException
2121
* fix content negotiation issue when sorting selected media types by quality value
22+
* raise RestClientException instead of IllegalArgumentException for unknown status codes
2223

2324

2425
Changes in version 3.1.1 (2012-02-16)

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

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 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.
@@ -20,6 +20,7 @@
2020
import java.io.InputStream;
2121
import java.nio.charset.Charset;
2222

23+
import org.springframework.http.HttpHeaders;
2324
import org.springframework.http.HttpStatus;
2425
import org.springframework.http.MediaType;
2526
import org.springframework.http.client.ClientHttpResponse;
@@ -28,10 +29,11 @@
2829
/**
2930
* Default implementation of the {@link ResponseErrorHandler} interface.
3031
*
31-
* <p>This error handler checks for the status code on the {@link ClientHttpResponse}: any code with series
32-
* {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR} or
33-
* {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR} is considered to be an error.
34-
* This behavior can be changed by overriding the {@link #hasError(HttpStatus)} method.
32+
* <p>This error handler checks for the status code on the {@link ClientHttpResponse}: any
33+
* code with series {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR} or
34+
* {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR} is considered to be an
35+
* error. This behavior can be changed by overriding the {@link #hasError(HttpStatus)}
36+
* method.
3537
*
3638
* @author Arjen Poutsma
3739
* @since 3.0
@@ -43,7 +45,18 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
4345
* Delegates to {@link #hasError(HttpStatus)} with the response status code.
4446
*/
4547
public boolean hasError(ClientHttpResponse response) throws IOException {
46-
return hasError(response.getStatusCode());
48+
return hasError(getStatusCode(response));
49+
}
50+
51+
private HttpStatus getStatusCode(ClientHttpResponse response) throws IOException {
52+
HttpStatus statusCode;
53+
try {
54+
statusCode = response.getStatusCode();
55+
}
56+
catch (IllegalArgumentException ex) {
57+
throw new RestClientException("Unknown status code [" + response.getRawStatusCode() + "]");
58+
}
59+
return statusCode;
4760
}
4861

4962
/**
@@ -67,31 +80,32 @@ protected boolean hasError(HttpStatus statusCode) {
6780
* and a {@link RestClientException} in other cases.
6881
*/
6982
public void handleError(ClientHttpResponse response) throws IOException {
70-
HttpStatus statusCode = response.getStatusCode();
71-
MediaType contentType = response.getHeaders().getContentType();
83+
HttpStatus statusCode = getStatusCode(response);
84+
HttpHeaders headers = response.getHeaders();
85+
MediaType contentType = headers.getContentType();
7286
Charset charset = contentType != null ? contentType.getCharSet() : null;
7387
byte[] body = getResponseBody(response);
7488
switch (statusCode.series()) {
7589
case CLIENT_ERROR:
76-
throw new HttpClientErrorException(statusCode, response.getStatusText(), body, charset);
90+
throw new HttpClientErrorException(statusCode, response.getStatusText(), headers, body, charset);
7791
case SERVER_ERROR:
78-
throw new HttpServerErrorException(statusCode, response.getStatusText(), body, charset);
92+
throw new HttpServerErrorException(statusCode, response.getStatusText(), headers, body, charset);
7993
default:
8094
throw new RestClientException("Unknown status code [" + statusCode + "]");
8195
}
8296
}
8397

8498
private byte[] getResponseBody(ClientHttpResponse response) {
8599
try {
86-
InputStream responseBody = response.getBody();
87-
if (responseBody != null) {
88-
return FileCopyUtils.copyToByteArray(responseBody);
89-
}
100+
InputStream responseBody = response.getBody();
101+
if (responseBody != null) {
102+
return FileCopyUtils.copyToByteArray(responseBody);
103+
}
90104
}
91105
catch (IOException ex) {
92-
// ignore
106+
// ignore
93107
}
94-
return new byte[0];
108+
return new byte[0];
95109
}
96110

97111
}

org.springframework.web/src/main/java/org/springframework/web/client/HttpClientErrorException.java

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 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,6 +18,7 @@
1818

1919
import java.nio.charset.Charset;
2020

21+
import org.springframework.http.HttpHeaders;
2122
import org.springframework.http.HttpStatus;
2223

2324
/**
@@ -29,16 +30,21 @@
2930
*/
3031
public class HttpClientErrorException extends HttpStatusCodeException {
3132

33+
private static final long serialVersionUID = 5177019431887513952L;
34+
35+
3236
/**
33-
* Construct a new instance of {@code HttpClientErrorException} based on a {@link HttpStatus}.
37+
* Construct a new instance of {@code HttpClientErrorException} based on an
38+
* {@link HttpStatus}.
3439
* @param statusCode the status code
3540
*/
3641
public HttpClientErrorException(HttpStatus statusCode) {
3742
super(statusCode);
3843
}
3944

4045
/**
41-
* Construct a new instance of {@code HttpClientErrorException} based on a {@link HttpStatus} and status text.
46+
* Construct a new instance of {@code HttpClientErrorException} based on an
47+
* {@link HttpStatus} and status text.
4248
* @param statusCode the status code
4349
* @param statusText the status text
4450
*/
@@ -47,18 +53,31 @@ public HttpClientErrorException(HttpStatus statusCode, String statusText) {
4753
}
4854

4955
/**
50-
* Construct a new instance of {@code HttpClientErrorException} based on a {@link HttpStatus}, status text, and
51-
* response body content.
52-
*
53-
* @param statusCode the status code
54-
* @param statusText the status text
55-
* @param responseBody the response body content, may be {@code null}
56+
* Construct a new instance of {@code HttpClientErrorException} based on an
57+
* {@link HttpStatus}, status text, and response body content.
58+
* @param statusCode the status code
59+
* @param statusText the status text
60+
* @param responseBody the response body content, may be {@code null}
5661
* @param responseCharset the response body charset, may be {@code null}
5762
*/
58-
public HttpClientErrorException(HttpStatus statusCode,
59-
String statusText,
60-
byte[] responseBody,
61-
Charset responseCharset) {
63+
public HttpClientErrorException(HttpStatus statusCode, String statusText,
64+
byte[] responseBody, Charset responseCharset) {
6265
super(statusCode, statusText, responseBody, responseCharset);
6366
}
67+
68+
/**
69+
* Construct a new instance of {@code HttpClientErrorException} based on an
70+
* {@link HttpStatus}, status text, and response body content.
71+
* @param statusCode the status code
72+
* @param statusText the status text
73+
* @param responseHeaders the response headers, may be {@code null}
74+
* @param responseBody the response body content, may be {@code null}
75+
* @param responseCharset the response body charset, may be {@code null}
76+
* @since 3.2
77+
*/
78+
public HttpClientErrorException(HttpStatus statusCode, String statusText,
79+
HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) {
80+
super(statusCode, statusText, responseHeaders, responseBody, responseCharset);
81+
}
82+
6483
}

org.springframework.web/src/main/java/org/springframework/web/client/HttpServerErrorException.java

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 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,6 +18,7 @@
1818

1919
import java.nio.charset.Charset;
2020

21+
import org.springframework.http.HttpHeaders;
2122
import org.springframework.http.HttpStatus;
2223

2324
/**
@@ -29,18 +30,21 @@
2930
*/
3031
public class HttpServerErrorException extends HttpStatusCodeException {
3132

33+
private static final long serialVersionUID = -2915754006618138282L;
34+
35+
3236
/**
33-
* Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus}.
34-
*
37+
* Construct a new instance of {@code HttpServerErrorException} based on an
38+
* {@link HttpStatus}.
3539
* @param statusCode the status code
3640
*/
3741
public HttpServerErrorException(HttpStatus statusCode) {
3842
super(statusCode);
3943
}
4044

4145
/**
42-
* Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus} and status text.
43-
*
46+
* Construct a new instance of {@code HttpServerErrorException} based on an
47+
* {@link HttpStatus} and status text.
4448
* @param statusCode the status code
4549
* @param statusText the status text
4650
*/
@@ -49,19 +53,31 @@ public HttpServerErrorException(HttpStatus statusCode, String statusText) {
4953
}
5054

5155
/**
52-
* Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus}, status text, and
53-
* response body content.
54-
*
56+
* Construct a new instance of {@code HttpServerErrorException} based on an
57+
* {@link HttpStatus}, status text, and response body content.
5558
* @param statusCode the status code
5659
* @param statusText the status text
5760
* @param responseBody the response body content, may be {@code null}
5861
* @param responseCharset the response body charset, may be {@code null}
5962
* @since 3.0.5
6063
*/
61-
public HttpServerErrorException(HttpStatus statusCode,
62-
String statusText,
63-
byte[] responseBody,
64-
Charset responseCharset) {
64+
public HttpServerErrorException(HttpStatus statusCode, String statusText,
65+
byte[] responseBody, Charset responseCharset) {
6566
super(statusCode, statusText, responseBody, responseCharset);
6667
}
68+
69+
/**
70+
* Construct a new instance of {@code HttpServerErrorException} based on a
71+
* {@link HttpStatus}, status text, and response body content.
72+
* @param statusCode the status code
73+
* @param statusText the status text
74+
* @param responseHeaders the response headers, may be {@code null}
75+
* @param responseBody the response body content, may be {@code null}
76+
* @param responseCharset the response body charset, may be {@code null}
77+
* @since 3.2
78+
*/
79+
public HttpServerErrorException(HttpStatus statusCode, String statusText,
80+
HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) {
81+
super(statusCode, statusText, responseHeaders, responseBody, responseCharset);
82+
}
6783
}

0 commit comments

Comments
 (0)