SPR-7591 - HttpStatusCodeException should contain response body

This commit is contained in:
Arjen Poutsma 2010-09-24 10:06:52 +00:00
parent 6e516b7281
commit 70cb81b4b5
5 changed files with 122 additions and 13 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@ -17,9 +17,12 @@
package org.springframework.web.client;
import java.io.IOException;
import java.nio.charset.Charset;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.FileCopyUtils;
/**
* Default implementation of the {@link ResponseErrorHandler} interface.
@ -64,14 +67,18 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
*/
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = response.getStatusCode();
MediaType contentType = response.getHeaders().getContentType();
Charset charset = contentType != null ? contentType.getCharSet() : null;
byte[] body = FileCopyUtils.copyToByteArray(response.getBody());
switch (statusCode.series()) {
case CLIENT_ERROR:
throw new HttpClientErrorException(statusCode, response.getStatusText());
throw new HttpClientErrorException(statusCode, response.getStatusText(), body, charset);
case SERVER_ERROR:
throw new HttpServerErrorException(statusCode, response.getStatusText());
throw new HttpServerErrorException(statusCode, response.getStatusText(), body, charset);
default:
throw new RestClientException("Unknown status code [" + statusCode + "]");
}
}
}

View File

@ -16,6 +16,8 @@
package org.springframework.web.client;
import java.nio.charset.Charset;
import org.springframework.http.HttpStatus;
/**
@ -44,4 +46,19 @@ public class HttpClientErrorException extends HttpStatusCodeException {
super(statusCode, statusText);
}
/**
* 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 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,
byte[] responseBody,
Charset responseCharset) {
super(statusCode, statusText, responseBody, responseCharset);
}
}

View File

@ -16,19 +16,22 @@
package org.springframework.web.client;
import java.nio.charset.Charset;
import org.springframework.http.HttpStatus;
/**
* Exception thrown when an HTTP 5xx is received.
*
* @author Arjen Poutsma
* @since 3.0
* @see DefaultResponseErrorHandler
* @since 3.0
*/
public class HttpServerErrorException extends HttpStatusCodeException {
/**
* Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus}.
*
* @param statusCode the status code
*/
public HttpServerErrorException(HttpStatus statusCode) {
@ -37,6 +40,7 @@ public class HttpServerErrorException extends HttpStatusCodeException {
/**
* Construct a new instance of {@code HttpServerErrorException} based on a {@link HttpStatus} and status text.
*
* @param statusCode the status code
* @param statusText the status text
*/
@ -44,4 +48,20 @@ public class HttpServerErrorException extends HttpStatusCodeException {
super(statusCode, statusText);
}
/**
* 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 responseBody the response body content, may be {@code null}
* @param responseCharset the response body charset, may be {@code null}
* @since 3.0.5
*/
public HttpServerErrorException(HttpStatus statusCode,
String statusText,
byte[] responseBody,
Charset responseCharset) {
super(statusCode, statusText, responseBody, responseCharset);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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,9 @@
package org.springframework.web.client;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import org.springframework.http.HttpStatus;
/**
@ -26,33 +29,56 @@ import org.springframework.http.HttpStatus;
*/
public abstract class HttpStatusCodeException extends RestClientException {
private static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
private final HttpStatus statusCode;
private final String statusText;
private final byte[] responseBody;
private final Charset responseCharset;
/**
* Construct a new instance of {@code HttpStatusCodeException} based on a {@link HttpStatus}.
*
* @param statusCode the status code
*/
protected HttpStatusCodeException(HttpStatus statusCode) {
super(statusCode.toString());
this.statusCode = statusCode;
this.statusText = statusCode.name();
this(statusCode, statusCode.name(), null, null);
}
/**
* Construct a new instance of {@code HttpStatusCodeException} based on a {@link HttpStatus} and status text.
*
* @param statusCode the status code
* @param statusText the status text
*/
protected HttpStatusCodeException(HttpStatus statusCode, String statusText) {
this(statusCode, statusText, null, null);
}
/**
* 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 responseBody the response body content, may be {@code null}
* @param responseCharset the response body charset, may be {@code null}
* @since 3.0.5
*/
protected HttpStatusCodeException(HttpStatus statusCode,
String statusText,
byte[] responseBody,
Charset responseCharset) {
super(statusCode.value() + " " + statusText);
this.statusCode = statusCode;
this.statusText = statusText;
this.responseBody = responseBody != null ? responseBody : new byte[0];
this.responseCharset = responseCharset != null ? responseCharset : DEFAULT_CHARSET;
}
/**
* Returns the HTTP status code.
*/
@ -67,4 +93,27 @@ public abstract class HttpStatusCodeException extends RestClientException {
return this.statusText;
}
/**
* Returns the response body as a byte array.
*
* @since 3.0.5
*/
public byte[] getResponseBodyAsByteArray() {
return responseBody;
}
/**
* Returns the response body as a string.
*
* @since 3.0.5
*/
public String getResponseBodyAsString() {
try {
return new String(responseBody, responseCharset.name());
}
catch (UnsupportedEncodingException ex) {
// should not occur
throw new InternalError(ex.getMessage());
}
}
}

View File

@ -145,14 +145,30 @@ public class RestTemplateIntegrationTests {
assertEquals("Invalid content", helloWorld, s);
}
@Test(expected = HttpClientErrorException.class)
@Test
public void notFound() {
try {
template.execute(URI + "/errors/notfound", HttpMethod.GET, null, null);
fail("HttpClientErrorException expected");
}
catch (HttpClientErrorException ex) {
assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode());
assertNotNull(ex.getStatusText());
assertNotNull(ex.getResponseBodyAsString());
}
}
@Test(expected = HttpServerErrorException.class)
@Test
public void serverError() {
try {
template.execute(URI + "/errors/server", HttpMethod.GET, null, null);
fail("HttpServerErrorException expected");
}
catch (HttpServerErrorException ex) {
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, ex.getStatusCode());
assertNotNull(ex.getStatusText());
assertNotNull(ex.getResponseBodyAsString());
}
}
@Test