diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java index 2bc17bb2c7c4..f261a7a7514c 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.http; +import java.io.Serializable; import java.net.URI; import java.nio.charset.Charset; import java.text.ParseException; @@ -54,7 +55,9 @@ * @author Arjen Poutsma * @since 3.0 */ -public class HttpHeaders implements MultiValueMap { +public class HttpHeaders implements MultiValueMap, Serializable { + + private static final long serialVersionUID = -8578554704772377436L; private static final String ACCEPT = "Accept"; diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java index 0615f7a823a9..4514eb38023f 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ 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; @@ -68,14 +69,15 @@ protected boolean hasError(HttpStatus statusCode) { */ 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 + "]"); } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java b/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java index 99de72b16072..a5aaeedf7c5a 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java @@ -18,6 +18,7 @@ import java.nio.charset.Charset; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; /** @@ -29,7 +30,7 @@ */ public class HttpClientErrorException extends HttpStatusCodeException { - private static final long serialVersionUID = 6777393766937023392L; + private static final long serialVersionUID = 5177019431887513952L; /** * Construct a new instance of {@code HttpClientErrorException} based on a {@link HttpStatus}. @@ -63,4 +64,22 @@ public HttpClientErrorException(HttpStatus statusCode, Charset responseCharset) { super(statusCode, statusText, responseBody, responseCharset); } + + /** + * Construct a new instance of {@code HttpClientErrorException} 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} + */ + public HttpClientErrorException(HttpStatus statusCode, + String statusText, + HttpHeaders responseHeaders, + byte[] responseBody, + Charset responseCharset) { + super(statusCode, statusText, responseHeaders, responseBody, responseCharset); + } } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java b/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java index 9549dcbd0e5a..7bd454b24b7e 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java @@ -18,6 +18,7 @@ import java.nio.charset.Charset; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; /** @@ -29,7 +30,7 @@ */ public class HttpServerErrorException extends HttpStatusCodeException { - private static final long serialVersionUID = -2565832100451369997L; + private static final long serialVersionUID = -2915754006618138282L; /** * Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus}. @@ -66,4 +67,23 @@ public HttpServerErrorException(HttpStatus statusCode, Charset responseCharset) { 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.0 + */ + public HttpServerErrorException(HttpStatus statusCode, + String statusText, + HttpHeaders responseHeaders, + byte[] responseBody, + Charset responseCharset) { + super(statusCode, statusText, responseHeaders, responseBody, responseCharset); + } } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java b/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java index e2396e0683d3..1f75e6bcce2e 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java @@ -19,6 +19,7 @@ import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; /** @@ -30,7 +31,7 @@ */ 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 { private final byte[] responseBody; + private final HttpHeaders responseHeaders; + private final String responseCharset; /** @@ -48,7 +51,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); } /** @@ -58,7 +61,7 @@ protected HttpStatusCodeException(HttpStatus statusCode) { * @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,29 @@ protected HttpStatusCodeException(HttpStatus statusCode, String statusText, byte[] responseBody, Charset responseCharset) { + this(statusCode, statusText, null, responseBody, responseCharset); + } + + /** + * Construct a new instance of {@code HttpStatusCodeException} 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.0 + */ + 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; } @@ -96,6 +119,15 @@ public String getStatusText() { return this.statusText; } + /** + * Returns the HTTP response headers. + * + * @since 3.2.0 + */ + public HttpHeaders getResponseHeaders() { + return this.responseHeaders; + } + /** * Returns the response body as a byte array. * diff --git a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java index 0c9866c19bee..519f2cd5d44a 100644 --- a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,9 @@ import static org.easymock.EasyMock.*; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** @author Arjen Poutsma */ public class DefaultResponseErrorHandlerTests { @@ -64,7 +66,7 @@ public void hasErrorFalse() throws Exception { verify(response); } - @Test(expected = HttpClientErrorException.class) + @Test public void handleError() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); @@ -76,7 +78,13 @@ public void handleError() throws Exception { replay(response); - handler.handleError(response); + try { + handler.handleError(response); + fail("expected HttpClientErrorException"); + } + catch (HttpClientErrorException e) { + assertSame(headers, e.getResponseHeaders()); + } verify(response); }