Browse Source

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
pull/87/head
Scott Andrews 14 years ago committed by Chris Beams
parent
commit
b992c3d3f2
  1. 6
      spring-web/src/main/java/org/springframework/http/HttpHeaders.java
  2. 8
      spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java
  3. 18
      spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java
  4. 17
      spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java
  5. 34
      spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java
  6. 10
      spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java

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

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.http;
import java.io.Serializable;
import java.net.URI;
import java.nio.charset.Charset;
@ -57,7 +59,9 @@ import org.springframework.util.StringUtils; @@ -57,7 +59,9 @@ import org.springframework.util.StringUtils;
* @author Arjen Poutsma
* @since 3.0
*/
public class HttpHeaders implements MultiValueMap<String, String> {
public class HttpHeaders implements MultiValueMap<String, String>, Serializable {
private static final long serialVersionUID = -8578554704772377436L;
private static final String ACCEPT = "Accept";

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

@ -20,6 +20,7 @@ import java.io.IOException; @@ -20,6 +20,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
@ -69,14 +70,15 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { @@ -69,14 +70,15 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
*/
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = response.getStatusCode();
MediaType contentType = response.getHeaders().getContentType();
HttpHeaders headers = response.getHeaders();
MediaType contentType = headers.getContentType();
Charset charset = contentType != null ? contentType.getCharSet() : null;
byte[] body = getResponseBody(response);
switch (statusCode.series()) {
case CLIENT_ERROR:
throw new HttpClientErrorException(statusCode, response.getStatusText(), body, charset);
throw new HttpClientErrorException(statusCode, response.getStatusText(), headers, body, charset);
case SERVER_ERROR:
throw new HttpServerErrorException(statusCode, response.getStatusText(), body, charset);
throw new HttpServerErrorException(statusCode, response.getStatusText(), headers, body, charset);
default:
throw new RestClientException("Unknown status code [" + statusCode + "]");
}

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

@ -18,6 +18,7 @@ package org.springframework.web.client; @@ -18,6 +18,7 @@ package org.springframework.web.client;
import java.nio.charset.Charset;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
/**
@ -29,7 +30,7 @@ import org.springframework.http.HttpStatus; @@ -29,7 +30,7 @@ import org.springframework.http.HttpStatus;
*/
public class HttpClientErrorException extends HttpStatusCodeException {
private static final long serialVersionUID = 6777393766937023392L;
private static final long serialVersionUID = 5177019431887513952L;
/**
@ -64,4 +65,19 @@ public class HttpClientErrorException extends HttpStatusCodeException { @@ -64,4 +65,19 @@ public class HttpClientErrorException extends HttpStatusCodeException {
super(statusCode, statusText, responseBody, responseCharset);
}
/**
* Construct a new instance of {@code HttpClientErrorException} based on an
* {@link HttpStatus}, status text, and response body content.
* @param statusCode the status code
* @param statusText the status text
* @param responseHeaders the response headers, may be {@code null}
* @param responseBody the response body content, may be {@code null}
* @param responseCharset the response body charset, may be {@code null}
* @since 3.2
*/
public HttpClientErrorException(HttpStatus statusCode, String statusText,
HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) {
super(statusCode, statusText, responseHeaders, responseBody, responseCharset);
}
}

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

@ -18,6 +18,7 @@ package org.springframework.web.client; @@ -18,6 +18,7 @@ package org.springframework.web.client;
import java.nio.charset.Charset;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
/**
@ -29,7 +30,7 @@ import org.springframework.http.HttpStatus; @@ -29,7 +30,7 @@ import org.springframework.http.HttpStatus;
*/
public class HttpServerErrorException extends HttpStatusCodeException {
private static final long serialVersionUID = -2565832100451369997L;
private static final long serialVersionUID = -2915754006618138282L;
/**
@ -65,4 +66,18 @@ public class HttpServerErrorException extends HttpStatusCodeException { @@ -65,4 +66,18 @@ public class HttpServerErrorException extends HttpStatusCodeException {
super(statusCode, statusText, responseBody, responseCharset);
}
/**
* Construct a new instance of {@code HttpServerErrorException} based on a
* {@link HttpStatus}, status text, and response body content.
* @param statusCode the status code
* @param statusText the status text
* @param responseHeaders the response headers, may be {@code null}
* @param responseBody the response body content, may be {@code null}
* @param responseCharset the response body charset, may be {@code null}
* @since 3.2
*/
public HttpServerErrorException(HttpStatus statusCode, String statusText,
HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) {
super(statusCode, statusText, responseHeaders, responseBody, responseCharset);
}
}

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

@ -19,6 +19,7 @@ package org.springframework.web.client; @@ -19,6 +19,7 @@ package org.springframework.web.client;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
/**
@ -30,7 +31,7 @@ import org.springframework.http.HttpStatus; @@ -30,7 +31,7 @@ import org.springframework.http.HttpStatus;
*/
public abstract class HttpStatusCodeException extends RestClientException {
private static final long serialVersionUID = 1549626836533638803L;
private static final long serialVersionUID = -5807494703720513267L;
private static final String DEFAULT_CHARSET = "ISO-8859-1";
@ -40,6 +41,8 @@ public abstract class HttpStatusCodeException extends RestClientException { @@ -40,6 +41,8 @@ public abstract class HttpStatusCodeException extends RestClientException {
private final byte[] responseBody;
private final HttpHeaders responseHeaders;
private final String responseCharset;
@ -49,7 +52,7 @@ public abstract class HttpStatusCodeException extends RestClientException { @@ -49,7 +52,7 @@ public abstract class HttpStatusCodeException extends RestClientException {
* @param statusCode the status code
*/
protected HttpStatusCodeException(HttpStatus statusCode) {
this(statusCode, statusCode.name(), null, null);
this(statusCode, statusCode.name(), null, null, null);
}
/**
@ -59,7 +62,7 @@ public abstract class HttpStatusCodeException extends RestClientException { @@ -59,7 +62,7 @@ public abstract class HttpStatusCodeException extends RestClientException {
* @param statusText the status text
*/
protected HttpStatusCodeException(HttpStatus statusCode, String statusText) {
this(statusCode, statusText, null, null);
this(statusCode, statusText, null, null, null);
}
/**
@ -75,9 +78,25 @@ public abstract class HttpStatusCodeException extends RestClientException { @@ -75,9 +78,25 @@ public abstract class HttpStatusCodeException extends RestClientException {
String statusText,
byte[] responseBody,
Charset responseCharset) {
this(statusCode, statusText, null, responseBody, responseCharset);
}
/**
* Construct a new instance of {@code HttpStatusCodeException} based on an
* {@link HttpStatus}, status text, and response body content.
* @param statusCode the status code
* @param statusText the status text
* @param responseHeaders the response headers, may be {@code null}
* @param responseBody the response body content, may be {@code null}
* @param responseCharset the response body charset, may be {@code null}
* @since 3.2
*/
protected HttpStatusCodeException(HttpStatus statusCode, String statusText,
HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset) {
super(statusCode.value() + " " + statusText);
this.statusCode = statusCode;
this.statusText = statusText;
this.responseHeaders = responseHeaders;
this.responseBody = responseBody != null ? responseBody : new byte[0];
this.responseCharset = responseCharset != null ? responseCharset.name() : DEFAULT_CHARSET;
}
@ -97,8 +116,17 @@ public abstract class HttpStatusCodeException extends RestClientException { @@ -97,8 +116,17 @@ public abstract class HttpStatusCodeException extends RestClientException {
return this.statusText;
}
/**
* Return the HTTP response headers.
* @since 3.2
*/
public HttpHeaders getResponseHeaders() {
return this.responseHeaders;
}
/**
* Return the response body as a byte array.
*
* @since 3.0.5
*/
public byte[] getResponseBodyAsByteArray() {

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

@ -68,7 +68,7 @@ public class DefaultResponseErrorHandlerTests { @@ -68,7 +68,7 @@ public class DefaultResponseErrorHandlerTests {
verify(response);
}
@Test(expected = HttpClientErrorException.class)
@Test
public void handleError() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
@ -80,7 +80,13 @@ public class DefaultResponseErrorHandlerTests { @@ -80,7 +80,13 @@ public class DefaultResponseErrorHandlerTests {
replay(response);
handler.handleError(response);
try {
handler.handleError(response);
fail("expected HttpClientErrorException");
}
catch (HttpClientErrorException e) {
assertSame(headers, e.getResponseHeaders());
}
verify(response);
}

Loading…
Cancel
Save