Skip to content

Commit b992c3d

Browse files
scothiscbeams
authored andcommitted
Include response headers in RestTemplate exceptions
Default HTTP error exceptions thrown from RestTemplate now include response headers in addition to the response body. In particular, this enables inspection of the Content-Type header allowing manual deserialization of the response body without guessing as to the content type. - introduce HttpStatusCodeException#getResponseHeaders - add constructor with headers param for HttpStatusCodeException, HttpClientErrorException and HttpServerErrorException - preserve exsisting constructor signatures - mark HttpHeaders as Serializable - generate new serialVersionUID where needed Issue: SPR-7938
1 parent bca2357 commit b992c3d

File tree

6 files changed

+82
-11
lines changed

6 files changed

+82
-11
lines changed

spring-web/src/main/java/org/springframework/http/HttpHeaders.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.http;
1818

19+
import java.io.Serializable;
20+
1921
import java.net.URI;
2022

2123
import java.nio.charset.Charset;
@@ -57,7 +59,9 @@
5759
* @author Arjen Poutsma
5860
* @since 3.0
5961
*/
60-
public class HttpHeaders implements MultiValueMap<String, String> {
62+
public class HttpHeaders implements MultiValueMap<String, String>, Serializable {
63+
64+
private static final long serialVersionUID = -8578554704772377436L;
6165

6266
private static final String ACCEPT = "Accept";
6367

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
@@ -69,14 +70,15 @@ protected boolean hasError(HttpStatus statusCode) {
6970
*/
7071
public void handleError(ClientHttpResponse response) throws IOException {
7172
HttpStatus statusCode = response.getStatusCode();
72-
MediaType contentType = response.getHeaders().getContentType();
73+
HttpHeaders headers = response.getHeaders();
74+
MediaType contentType = headers.getContentType();
7375
Charset charset = contentType != null ? contentType.getCharSet() : null;
7476
byte[] body = getResponseBody(response);
7577
switch (statusCode.series()) {
7678
case CLIENT_ERROR:
77-
throw new HttpClientErrorException(statusCode, response.getStatusText(), body, charset);
79+
throw new HttpClientErrorException(statusCode, response.getStatusText(), headers, body, charset);
7880
case SERVER_ERROR:
79-
throw new HttpServerErrorException(statusCode, response.getStatusText(), body, charset);
81+
throw new HttpServerErrorException(statusCode, response.getStatusText(), headers, body, charset);
8082
default:
8183
throw new RestClientException("Unknown status code [" + statusCode + "]");
8284
}

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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,7 +30,7 @@
2930
*/
3031
public class HttpClientErrorException extends HttpStatusCodeException {
3132

32-
private static final long serialVersionUID = 6777393766937023392L;
33+
private static final long serialVersionUID = 5177019431887513952L;
3334

3435

3536
/**
@@ -64,4 +65,19 @@ public HttpClientErrorException(HttpStatus statusCode, String statusText,
6465
super(statusCode, statusText, responseBody, responseCharset);
6566
}
6667

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+
6783
}

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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,7 +30,7 @@
2930
*/
3031
public class HttpServerErrorException extends HttpStatusCodeException {
3132

32-
private static final long serialVersionUID = -2565832100451369997L;
33+
private static final long serialVersionUID = -2915754006618138282L;
3334

3435

3536
/**
@@ -65,4 +66,18 @@ public HttpServerErrorException(HttpStatus statusCode, String statusText,
6566
super(statusCode, statusText, responseBody, responseCharset);
6667
}
6768

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+
}
6883
}

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

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.UnsupportedEncodingException;
2020
import java.nio.charset.Charset;
2121

22+
import org.springframework.http.HttpHeaders;
2223
import org.springframework.http.HttpStatus;
2324

2425
/**
@@ -30,7 +31,7 @@
3031
*/
3132
public abstract class HttpStatusCodeException extends RestClientException {
3233

33-
private static final long serialVersionUID = 1549626836533638803L;
34+
private static final long serialVersionUID = -5807494703720513267L;
3435

3536
private static final String DEFAULT_CHARSET = "ISO-8859-1";
3637

@@ -40,6 +41,8 @@ public abstract class HttpStatusCodeException extends RestClientException {
4041

4142
private final byte[] responseBody;
4243

44+
private final HttpHeaders responseHeaders;
45+
4346
private final String responseCharset;
4447

4548

@@ -49,7 +52,7 @@ public abstract class HttpStatusCodeException extends RestClientException {
4952
* @param statusCode the status code
5053
*/
5154
protected HttpStatusCodeException(HttpStatus statusCode) {
52-
this(statusCode, statusCode.name(), null, null);
55+
this(statusCode, statusCode.name(), null, null, null);
5356
}
5457

5558
/**
@@ -59,7 +62,7 @@ protected HttpStatusCodeException(HttpStatus statusCode) {
5962
* @param statusText the status text
6063
*/
6164
protected HttpStatusCodeException(HttpStatus statusCode, String statusText) {
62-
this(statusCode, statusText, null, null);
65+
this(statusCode, statusText, null, null, null);
6366
}
6467

6568
/**
@@ -75,9 +78,25 @@ protected HttpStatusCodeException(HttpStatus statusCode,
7578
String statusText,
7679
byte[] responseBody,
7780
Charset responseCharset) {
81+
this(statusCode, statusText, null, responseBody, responseCharset);
82+
}
83+
84+
/**
85+
* Construct a new instance of {@code HttpStatusCodeException} based on an
86+
* {@link HttpStatus}, status text, and response body content.
87+
* @param statusCode the status code
88+
* @param statusText the status text
89+
* @param responseHeaders the response headers, may be {@code null}
90+
* @param responseBody the response body content, may be {@code null}
91+
* @param responseCharset the response body charset, may be {@code null}
92+
* @since 3.2
93+
*/
94+
protected HttpStatusCodeException(HttpStatus statusCode, String statusText,
95+
HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) {
7896
super(statusCode.value() + " " + statusText);
7997
this.statusCode = statusCode;
8098
this.statusText = statusText;
99+
this.responseHeaders = responseHeaders;
81100
this.responseBody = responseBody != null ? responseBody : new byte[0];
82101
this.responseCharset = responseCharset != null ? responseCharset.name() : DEFAULT_CHARSET;
83102
}
@@ -97,8 +116,17 @@ public String getStatusText() {
97116
return this.statusText;
98117
}
99118

119+
/**
120+
* Return the HTTP response headers.
121+
* @since 3.2
122+
*/
123+
public HttpHeaders getResponseHeaders() {
124+
return this.responseHeaders;
125+
}
126+
100127
/**
101128
* Return the response body as a byte array.
129+
*
102130
* @since 3.0.5
103131
*/
104132
public byte[] getResponseBodyAsByteArray() {

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public void hasErrorFalse() throws Exception {
6868
verify(response);
6969
}
7070

71-
@Test(expected = HttpClientErrorException.class)
71+
@Test
7272
public void handleError() throws Exception {
7373
HttpHeaders headers = new HttpHeaders();
7474
headers.setContentType(MediaType.TEXT_PLAIN);
@@ -80,7 +80,13 @@ public void handleError() throws Exception {
8080

8181
replay(response);
8282

83-
handler.handleError(response);
83+
try {
84+
handler.handleError(response);
85+
fail("expected HttpClientErrorException");
86+
}
87+
catch (HttpClientErrorException e) {
88+
assertSame(headers, e.getResponseHeaders());
89+
}
8490

8591
verify(response);
8692
}

0 commit comments

Comments
 (0)