提交 e6a65804 编写于 作者: R Rossen Stoyanchev

Merge pull request #1956

Closes gh-1956
......@@ -16,8 +16,13 @@
package org.springframework.web.client;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
......@@ -25,6 +30,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
/**
* Spring's default implementation of the {@link ResponseErrorHandler} interface.
......@@ -96,12 +102,51 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
if (statusCode == null) {
throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(),
String message = getErrorMessage(
response.getRawStatusCode(), response.getStatusText(),
getResponseBody(response), getCharset(response));
throw new UnknownHttpStatusCodeException(message,
response.getRawStatusCode(), response.getStatusText(),
response.getHeaders(), getResponseBody(response), getCharset(response));
}
handleError(response, statusCode);
}
/**
* Return error message with details from the response body, possibly truncated:
* <pre>
* 404 Not Found: [{'id': 123, 'message': 'my very long... (500 bytes)]
* </pre>
*/
private String getErrorMessage(
int rawStatusCode, String statusText, @Nullable byte[] responseBody, @Nullable Charset charset) {
String preface = rawStatusCode + " " + statusText + ": ";
if (ObjectUtils.isEmpty(responseBody)) {
return preface + "[no body]";
}
charset = charset == null ? StandardCharsets.UTF_8 : charset;
int maxChars = 200;
if (responseBody.length < maxChars * 2) {
return preface + "[" + new String(responseBody, charset) + "]";
}
try {
Reader reader = new InputStreamReader(new ByteArrayInputStream(responseBody), charset);
CharBuffer buffer = CharBuffer.allocate(maxChars);
reader.read(buffer);
reader.close();
buffer.flip();
return preface + "[" + buffer.toString() + "... (" + responseBody.length + " bytes)]";
}
catch (IOException ex) {
// should never happen
throw new IllegalStateException(ex);
}
}
/**
* Handle the error in the given response with the given resolved status code.
* <p>The default implementation throws an {@link HttpClientErrorException}
......@@ -118,13 +163,15 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
HttpHeaders headers = response.getHeaders();
byte[] body = getResponseBody(response);
Charset charset = getCharset(response);
String message = getErrorMessage(statusCode.value(), statusText, body, charset);
switch (statusCode.series()) {
case CLIENT_ERROR:
throw HttpClientErrorException.create(statusCode, statusText, headers, body, charset);
throw HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset);
case SERVER_ERROR:
throw HttpServerErrorException.create(statusCode, statusText, headers, body, charset);
throw HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset);
default:
throw new UnknownHttpStatusCodeException(statusCode.value(), statusText, headers, body, charset);
throw new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset);
}
}
......
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
......@@ -66,6 +66,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
super(statusCode, statusText, headers, body, responseCharset);
}
/**
* Constructor with a status code and status text, headers, and content,
* and an prepared message.
* @since 5.2.2
*/
public HttpClientErrorException(String message, HttpStatus statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset responseCharset) {
super(message, statusCode, statusText, headers, body, responseCharset);
}
/**
* Create {@code HttpClientErrorException} or an HTTP status specific sub-class.
......@@ -74,31 +85,66 @@ public class HttpClientErrorException extends HttpStatusCodeException {
public static HttpClientErrorException create(
HttpStatus statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
return create(null, statusCode, statusText, headers, body, charset);
}
/**
* Variant of {@link #create(HttpStatus, String, HttpHeaders, byte[], Charset)}
* with an optional prepared message.
* @since 5.2.2
*/
public static HttpClientErrorException create(@Nullable String message, HttpStatus statusCode,
String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
switch (statusCode) {
case BAD_REQUEST:
return new HttpClientErrorException.BadRequest(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.BadRequest(message, statusText, headers, body, charset) :
new HttpClientErrorException.BadRequest(statusText, headers, body, charset);
case UNAUTHORIZED:
return new HttpClientErrorException.Unauthorized(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.Unauthorized(message, statusText, headers, body, charset) :
new HttpClientErrorException.Unauthorized(statusText, headers, body, charset);
case FORBIDDEN:
return new HttpClientErrorException.Forbidden(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.Forbidden(message, statusText, headers, body, charset) :
new HttpClientErrorException.Forbidden(statusText, headers, body, charset);
case NOT_FOUND:
return new HttpClientErrorException.NotFound(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.NotFound(message, statusText, headers, body, charset) :
new HttpClientErrorException.NotFound(statusText, headers, body, charset);
case METHOD_NOT_ALLOWED:
return new HttpClientErrorException.MethodNotAllowed(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.MethodNotAllowed(message, statusText, headers, body, charset) :
new HttpClientErrorException.MethodNotAllowed(statusText, headers, body, charset);
case NOT_ACCEPTABLE:
return new HttpClientErrorException.NotAcceptable(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.NotAcceptable(message, statusText, headers, body, charset) :
new HttpClientErrorException.NotAcceptable(statusText, headers, body, charset);
case CONFLICT:
return new HttpClientErrorException.Conflict(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.Conflict(message, statusText, headers, body, charset) :
new HttpClientErrorException.Conflict(statusText, headers, body, charset);
case GONE:
return new HttpClientErrorException.Gone(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.Gone(message, statusText, headers, body, charset) :
new HttpClientErrorException.Gone(statusText, headers, body, charset);
case UNSUPPORTED_MEDIA_TYPE:
return new HttpClientErrorException.UnsupportedMediaType(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.UnsupportedMediaType(message, statusText, headers, body, charset) :
new HttpClientErrorException.UnsupportedMediaType(statusText, headers, body, charset);
case TOO_MANY_REQUESTS:
return new HttpClientErrorException.TooManyRequests(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.TooManyRequests(message, statusText, headers, body, charset) :
new HttpClientErrorException.TooManyRequests(statusText, headers, body, charset);
case UNPROCESSABLE_ENTITY:
return new HttpClientErrorException.UnprocessableEntity(statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException.UnprocessableEntity(message, statusText, headers, body, charset) :
new HttpClientErrorException.UnprocessableEntity(statusText, headers, body, charset);
default:
return new HttpClientErrorException(statusCode, statusText, headers, body, charset);
return message != null ?
new HttpClientErrorException(message, statusCode, statusText, headers, body, charset) :
new HttpClientErrorException(statusCode, statusText, headers, body, charset);
}
}
......@@ -110,11 +156,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class BadRequest extends HttpClientErrorException {
public static final class BadRequest extends HttpClientErrorException {
BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.BAD_REQUEST, statusText, headers, body, charset);
}
private BadRequest(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.BAD_REQUEST, statusText, headers, body, charset);
}
}
/**
......@@ -122,11 +174,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class Unauthorized extends HttpClientErrorException {
public static final class Unauthorized extends HttpClientErrorException {
Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.UNAUTHORIZED, statusText, headers, body, charset);
}
private Unauthorized(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.UNAUTHORIZED, statusText, headers, body, charset);
}
}
/**
......@@ -134,11 +192,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class Forbidden extends HttpClientErrorException {
public static final class Forbidden extends HttpClientErrorException {
Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.FORBIDDEN, statusText, headers, body, charset);
}
private Forbidden(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.FORBIDDEN, statusText, headers, body, charset);
}
}
/**
......@@ -146,11 +210,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class NotFound extends HttpClientErrorException {
public static final class NotFound extends HttpClientErrorException {
NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.NOT_FOUND, statusText, headers, body, charset);
}
private NotFound(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.NOT_FOUND, statusText, headers, body, charset);
}
}
/**
......@@ -158,11 +228,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class MethodNotAllowed extends HttpClientErrorException {
public static final class MethodNotAllowed extends HttpClientErrorException {
MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.METHOD_NOT_ALLOWED, statusText, headers, body, charset);
}
private MethodNotAllowed(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.METHOD_NOT_ALLOWED, statusText, headers, body, charset);
}
}
/**
......@@ -170,11 +246,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class NotAcceptable extends HttpClientErrorException {
public static final class NotAcceptable extends HttpClientErrorException {
NotAcceptable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private NotAcceptable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.NOT_ACCEPTABLE, statusText, headers, body, charset);
}
private NotAcceptable(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.NOT_ACCEPTABLE, statusText, headers, body, charset);
}
}
/**
......@@ -182,11 +264,15 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class Conflict extends HttpClientErrorException {
public static final class Conflict extends HttpClientErrorException {
Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.CONFLICT, statusText, headers, body, charset);
}
private Conflict(String message, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.CONFLICT, statusText, headers, body, charset);
}
}
/**
......@@ -194,11 +280,15 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class Gone extends HttpClientErrorException {
public static final class Gone extends HttpClientErrorException {
Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.GONE, statusText, headers, body, charset);
}
private Gone(String message, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.GONE, statusText, headers, body, charset);
}
}
/**
......@@ -206,11 +296,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class UnsupportedMediaType extends HttpClientErrorException {
public static final class UnsupportedMediaType extends HttpClientErrorException {
UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, headers, body, charset);
}
private UnsupportedMediaType(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, headers, body, charset);
}
}
/**
......@@ -218,11 +314,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class UnprocessableEntity extends HttpClientErrorException {
public static final class UnprocessableEntity extends HttpClientErrorException {
UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.UNPROCESSABLE_ENTITY, statusText, headers, body, charset);
}
private UnprocessableEntity(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.UNPROCESSABLE_ENTITY, statusText, headers, body, charset);
}
}
/**
......@@ -230,11 +332,17 @@ public class HttpClientErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class TooManyRequests extends HttpClientErrorException {
public static final class TooManyRequests extends HttpClientErrorException {
TooManyRequests(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private TooManyRequests(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.TOO_MANY_REQUESTS, statusText, headers, body, charset);
}
private TooManyRequests(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.TOO_MANY_REQUESTS, statusText, headers, body, charset);
}
}
}
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
......@@ -66,27 +66,60 @@ public class HttpServerErrorException extends HttpStatusCodeException {
super(statusCode, statusText, headers, body, charset);
}
/**
* Constructor with a status code and status text, headers, content, and an
* prepared message.
* @since 5.2.2
*/
public HttpServerErrorException(String message, HttpStatus statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset) {
super(message, statusCode, statusText, headers, body, charset);
}
/**
* Create an {@code HttpServerErrorException} or an HTTP status specific sub-class.
* @since 5.1
*/
public static HttpServerErrorException create(
HttpStatus statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
public static HttpServerErrorException create(HttpStatus statusCode,
String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
return create(null, statusCode, statusText, headers, body, charset);
}
/**
* Variant of {@link #create(String, HttpStatus, String, HttpHeaders, byte[], Charset)}
* with an optional prepared message.
* @since 5.2.2.
*/
public static HttpServerErrorException create(@Nullable String message, HttpStatus statusCode,
String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
switch (statusCode) {
case INTERNAL_SERVER_ERROR:
return new HttpServerErrorException.InternalServerError(statusText, headers, body, charset);
return message != null ?
new HttpServerErrorException.InternalServerError(message, statusText, headers, body, charset) :
new HttpServerErrorException.InternalServerError(statusText, headers, body, charset);
case NOT_IMPLEMENTED:
return new HttpServerErrorException.NotImplemented(statusText, headers, body, charset);
return message != null ?
new HttpServerErrorException.NotImplemented(message, statusText, headers, body, charset) :
new HttpServerErrorException.NotImplemented(statusText, headers, body, charset);
case BAD_GATEWAY:
return new HttpServerErrorException.BadGateway(statusText, headers, body, charset);
return message != null ?
new HttpServerErrorException.BadGateway(message, statusText, headers, body, charset) :
new HttpServerErrorException.BadGateway(statusText, headers, body, charset);
case SERVICE_UNAVAILABLE:
return new HttpServerErrorException.ServiceUnavailable(statusText, headers, body, charset);
return message != null ?
new HttpServerErrorException.ServiceUnavailable(message, statusText, headers, body, charset) :
new HttpServerErrorException.ServiceUnavailable(statusText, headers, body, charset);
case GATEWAY_TIMEOUT:
return new HttpServerErrorException.GatewayTimeout(statusText, headers, body, charset);
return message != null ?
new HttpServerErrorException.GatewayTimeout(message, statusText, headers, body, charset) :
new HttpServerErrorException.GatewayTimeout(statusText, headers, body, charset);
default:
return new HttpServerErrorException(statusCode, statusText, headers, body, charset);
return message != null ?
new HttpServerErrorException(message, statusCode, statusText, headers, body, charset) :
new HttpServerErrorException(statusCode, statusText, headers, body, charset);
}
}
......@@ -98,11 +131,17 @@ public class HttpServerErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class InternalServerError extends HttpServerErrorException {
public static final class InternalServerError extends HttpServerErrorException {
InternalServerError(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private InternalServerError(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.INTERNAL_SERVER_ERROR, statusText, headers, body, charset);
}
private InternalServerError(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.INTERNAL_SERVER_ERROR, statusText, headers, body, charset);
}
}
/**
......@@ -110,11 +149,17 @@ public class HttpServerErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class NotImplemented extends HttpServerErrorException {
public static final class NotImplemented extends HttpServerErrorException {
NotImplemented(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private NotImplemented(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.NOT_IMPLEMENTED, statusText, headers, body, charset);
}
private NotImplemented(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.NOT_IMPLEMENTED, statusText, headers, body, charset);
}
}
/**
......@@ -122,11 +167,17 @@ public class HttpServerErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class BadGateway extends HttpServerErrorException {
public static final class BadGateway extends HttpServerErrorException {
BadGateway(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private BadGateway(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.BAD_GATEWAY, statusText, headers, body, charset);
}
private BadGateway(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.BAD_GATEWAY, statusText, headers, body, charset);
}
}
/**
......@@ -134,11 +185,17 @@ public class HttpServerErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class ServiceUnavailable extends HttpServerErrorException {
public static final class ServiceUnavailable extends HttpServerErrorException {
ServiceUnavailable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private ServiceUnavailable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.SERVICE_UNAVAILABLE, statusText, headers, body, charset);
}
private ServiceUnavailable(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.SERVICE_UNAVAILABLE, statusText, headers, body, charset);
}
}
/**
......@@ -146,11 +203,17 @@ public class HttpServerErrorException extends HttpStatusCodeException {
* @since 5.1
*/
@SuppressWarnings("serial")
public static class GatewayTimeout extends HttpServerErrorException {
public static final class GatewayTimeout extends HttpServerErrorException {
GatewayTimeout(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
private GatewayTimeout(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.GATEWAY_TIMEOUT, statusText, headers, body, charset);
}
private GatewayTimeout(String message, String statusText,
HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(message, HttpStatus.GATEWAY_TIMEOUT, statusText, headers, body, charset);
}
}
}
......@@ -83,8 +83,25 @@ public abstract class HttpStatusCodeException extends RestClientResponseExceptio
protected HttpStatusCodeException(HttpStatus statusCode, String statusText,
@Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) {
super(getMessage(statusCode, statusText), statusCode.value(), statusText,
responseHeaders, responseBody, responseCharset);
this(getMessage(statusCode, statusText),
statusCode, statusText, responseHeaders, responseBody, responseCharset);
}
/**
* Construct instance with an {@link HttpStatus}, status text, content, and
* a response charset.
* @param message the exception message
* @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 5.2.2
*/
protected HttpStatusCodeException(String message, HttpStatus statusCode, String statusText,
@Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) {
super(message, statusCode.value(), statusText, responseHeaders, responseBody, responseCharset);
this.statusCode = statusCode;
}
......
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 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.
......@@ -45,8 +45,23 @@ public class UnknownHttpStatusCodeException extends RestClientResponseException
public UnknownHttpStatusCodeException(int rawStatusCode, String statusText, @Nullable HttpHeaders responseHeaders,
@Nullable byte[] responseBody, @Nullable Charset responseCharset) {
super("Unknown status code [" + rawStatusCode + "]" + " " + statusText,
this("Unknown status code [" + rawStatusCode + "]" + " " + statusText,
rawStatusCode, statusText, responseHeaders, responseBody, responseCharset);
}
/**
* Construct a new instance of {@code HttpStatusCodeException} based on an
* {@link HttpStatus}, status text, and response body content.
* @param rawStatusCode the raw status code value
* @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 5.2.2
*/
public UnknownHttpStatusCodeException(String message, int rawStatusCode, String statusText,
@Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) {
super(message, rawStatusCode, statusText, responseHeaders, responseBody, responseCharset);
}
}
......@@ -19,8 +19,10 @@ package org.springframework.web.client;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
......@@ -69,9 +71,28 @@ public class DefaultResponseErrorHandlerTests {
given(response.getHeaders()).willReturn(headers);
given(response.getBody()).willReturn(new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)));
assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy(() ->
handler.handleError(response))
.satisfies(ex -> assertThat(ex.getResponseHeaders()).isSameAs(headers));
assertThatExceptionOfType(HttpClientErrorException.class)
.isThrownBy(() -> handler.handleError(response))
.satisfies(ex -> assertThat(ex.getResponseHeaders()).isSameAs(headers))
.satisfies(ex -> assertThat(ex.getMessage()).isEqualTo("404 Not Found: [Hello World]"));
}
@Test
public void handleErrorWithLongBody() throws Exception {
Function<Integer, String> bodyGenerator =
size -> Flux.just("a").repeat(size-1).reduce((s, s2) -> s + s2).block();
given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value());
given(response.getStatusText()).willReturn("Not Found");
given(response.getHeaders()).willReturn(new HttpHeaders());
given(response.getBody()).willReturn(
new ByteArrayInputStream(bodyGenerator.apply(500).getBytes(StandardCharsets.UTF_8)));
assertThatExceptionOfType(HttpClientErrorException.class)
.isThrownBy(() -> handler.handleError(response))
.satisfies(ex -> assertThat(ex.getMessage()).isEqualTo(
"404 Not Found: [" + bodyGenerator.apply(200) + "... (500 bytes)]"));
}
@Test
......@@ -84,8 +105,7 @@ public class DefaultResponseErrorHandlerTests {
given(response.getHeaders()).willReturn(headers);
given(response.getBody()).willThrow(new IOException());
assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy(() ->
handler.handleError(response));
assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy(() -> handler.handleError(response));
}
@Test
......
......@@ -254,7 +254,7 @@ class RestTemplateIntegrationTests extends AbstractMockWebServerTests {
template.execute(baseUrl + "/status/badrequest", HttpMethod.GET, null, null))
.satisfies(ex -> {
assertThat(ex.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
assertThat(ex.getMessage()).isEqualTo("400 Client Error");
assertThat(ex.getMessage()).isEqualTo("400 Client Error: [no body]");
});
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册