|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2012 the original author or authors. |
|
|
|
* Copyright 2002-2017 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -17,7 +17,6 @@ |
|
|
|
package org.springframework.web.client; |
|
|
|
package org.springframework.web.client; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
|
|
|
|
import java.nio.charset.Charset; |
|
|
|
import java.nio.charset.Charset; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.http.HttpHeaders; |
|
|
|
import org.springframework.http.HttpHeaders; |
|
|
|
@ -27,13 +26,12 @@ import org.springframework.http.client.ClientHttpResponse; |
|
|
|
import org.springframework.util.FileCopyUtils; |
|
|
|
import org.springframework.util.FileCopyUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Default implementation of the {@link ResponseErrorHandler} interface. |
|
|
|
* Spring's default implementation of the {@link ResponseErrorHandler} interface. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>This error handler checks for the status code on the {@link ClientHttpResponse}: any |
|
|
|
* <p>This error handler checks for the status code on the {@link ClientHttpResponse}: |
|
|
|
* code with series {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR} or |
|
|
|
* Any code with series {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR} or |
|
|
|
* {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR} is considered to be an |
|
|
|
* {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR} is considered to be an |
|
|
|
* error. This behavior can be changed by overriding the {@link #hasError(HttpStatus)} |
|
|
|
* error. This behavior can be changed by overriding the {@link #hasError(HttpStatus)} method. |
|
|
|
* method. |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
@ -50,16 +48,45 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { |
|
|
|
return hasError(getHttpStatusCode(response)); |
|
|
|
return hasError(getHttpStatusCode(response)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private HttpStatus getHttpStatusCode(ClientHttpResponse response) throws IOException { |
|
|
|
/** |
|
|
|
HttpStatus statusCode; |
|
|
|
* This default implementation throws a {@link HttpClientErrorException} if the response status code |
|
|
|
|
|
|
|
* is {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR}, a {@link HttpServerErrorException} |
|
|
|
|
|
|
|
* if it is {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}, |
|
|
|
|
|
|
|
* and a {@link RestClientException} in other cases. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void handleError(ClientHttpResponse response) throws IOException { |
|
|
|
|
|
|
|
HttpStatus statusCode = getHttpStatusCode(response); |
|
|
|
|
|
|
|
switch (statusCode.series()) { |
|
|
|
|
|
|
|
case CLIENT_ERROR: |
|
|
|
|
|
|
|
throw new HttpClientErrorException(statusCode, response.getStatusText(), |
|
|
|
|
|
|
|
response.getHeaders(), getResponseBody(response), getCharset(response)); |
|
|
|
|
|
|
|
case SERVER_ERROR: |
|
|
|
|
|
|
|
throw new HttpServerErrorException(statusCode, response.getStatusText(), |
|
|
|
|
|
|
|
response.getHeaders(), getResponseBody(response), getCharset(response)); |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new RestClientException("Unknown status code [" + statusCode + "]"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Determine the HTTP status of the given response. |
|
|
|
|
|
|
|
* @param response the response to inspect |
|
|
|
|
|
|
|
* @return the associated HTTP status |
|
|
|
|
|
|
|
* @throws IOException in case of I/O errors |
|
|
|
|
|
|
|
* @throws UnknownHttpStatusCodeException in case of an unknown status code |
|
|
|
|
|
|
|
* that cannot be represented with the {@link HttpStatus} enum |
|
|
|
|
|
|
|
* @since 4.3.8 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected HttpStatus getHttpStatusCode(ClientHttpResponse response) throws IOException { |
|
|
|
try { |
|
|
|
try { |
|
|
|
statusCode = response.getStatusCode(); |
|
|
|
return response.getStatusCode(); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (IllegalArgumentException ex) { |
|
|
|
catch (IllegalArgumentException ex) { |
|
|
|
throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), |
|
|
|
throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(), |
|
|
|
response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); |
|
|
|
response.getHeaders(), getResponseBody(response), getCharset(response)); |
|
|
|
} |
|
|
|
} |
|
|
|
return statusCode; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -70,6 +97,7 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { |
|
|
|
* Can be overridden in subclasses. |
|
|
|
* Can be overridden in subclasses. |
|
|
|
* @param statusCode the HTTP status code |
|
|
|
* @param statusCode the HTTP status code |
|
|
|
* @return {@code true} if the response has an error; {@code false} otherwise |
|
|
|
* @return {@code true} if the response has an error; {@code false} otherwise |
|
|
|
|
|
|
|
* @see #getHttpStatusCode(ClientHttpResponse) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected boolean hasError(HttpStatus statusCode) { |
|
|
|
protected boolean hasError(HttpStatus statusCode) { |
|
|
|
return (statusCode.series() == HttpStatus.Series.CLIENT_ERROR || |
|
|
|
return (statusCode.series() == HttpStatus.Series.CLIENT_ERROR || |
|
|
|
@ -77,32 +105,27 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* This default implementation throws a {@link HttpClientErrorException} if the response status code |
|
|
|
* Determine the charset of the response (for inclusion in a status exception). |
|
|
|
* is {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR}, a {@link HttpServerErrorException} |
|
|
|
* @param response the response to inspect |
|
|
|
* if it is {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR}, |
|
|
|
* @return the associated charset, or {@code null} if none |
|
|
|
* and a {@link RestClientException} in other cases. |
|
|
|
* @since 4.3.8 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
protected Charset getCharset(ClientHttpResponse response) { |
|
|
|
public void handleError(ClientHttpResponse response) throws IOException { |
|
|
|
HttpHeaders headers = response.getHeaders(); |
|
|
|
HttpStatus statusCode = getHttpStatusCode(response); |
|
|
|
MediaType contentType = headers.getContentType(); |
|
|
|
switch (statusCode.series()) { |
|
|
|
return (contentType != null ? contentType.getCharset() : null); |
|
|
|
case CLIENT_ERROR: |
|
|
|
|
|
|
|
throw new HttpClientErrorException(statusCode, response.getStatusText(), |
|
|
|
|
|
|
|
response.getHeaders(), getResponseBody(response), getCharset(response)); |
|
|
|
|
|
|
|
case SERVER_ERROR: |
|
|
|
|
|
|
|
throw new HttpServerErrorException(statusCode, response.getStatusText(), |
|
|
|
|
|
|
|
response.getHeaders(), getResponseBody(response), getCharset(response)); |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new RestClientException("Unknown status code [" + statusCode + "]"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private byte[] getResponseBody(ClientHttpResponse response) { |
|
|
|
/** |
|
|
|
|
|
|
|
* Read the body of the given response (for inclusion in a status exception). |
|
|
|
|
|
|
|
* @param response the response to inspect |
|
|
|
|
|
|
|
* @return the response body as a byte array, |
|
|
|
|
|
|
|
* or an empty byte array if the body could not be read |
|
|
|
|
|
|
|
* @since 4.3.8 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected byte[] getResponseBody(ClientHttpResponse response) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
InputStream responseBody = response.getBody(); |
|
|
|
return FileCopyUtils.copyToByteArray(response.getBody()); |
|
|
|
if (responseBody != null) { |
|
|
|
|
|
|
|
return FileCopyUtils.copyToByteArray(responseBody); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
catch (IOException ex) { |
|
|
|
catch (IOException ex) { |
|
|
|
// ignore
|
|
|
|
// ignore
|
|
|
|
@ -110,10 +133,4 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { |
|
|
|
return new byte[0]; |
|
|
|
return new byte[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Charset getCharset(ClientHttpResponse response) { |
|
|
|
|
|
|
|
HttpHeaders headers = response.getHeaders(); |
|
|
|
|
|
|
|
MediaType contentType = headers.getContentType(); |
|
|
|
|
|
|
|
return contentType != null ? contentType.getCharset() : null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|