Hierarchy under WebClientResponseException
Issue: SPR-17145
This commit is contained in:
parent
c90ab5fb0a
commit
a0dfdfcac3
|
@ -463,9 +463,7 @@ class DefaultWebClient implements WebClient {
|
|||
.map(MimeType::getCharset)
|
||||
.orElse(StandardCharsets.ISO_8859_1);
|
||||
if (HttpStatus.resolve(response.rawStatusCode()) != null) {
|
||||
String msg = String.format("ClientResponse has erroneous status code: %d %s",
|
||||
response.statusCode().value(), response.statusCode().getReasonPhrase());
|
||||
return new WebClientResponseException(msg,
|
||||
return WebClientResponseException.create(
|
||||
response.statusCode().value(),
|
||||
response.statusCode().getReasonPhrase(),
|
||||
response.headers().asHttpHeaders(),
|
||||
|
|
|
@ -46,25 +46,28 @@ public class WebClientResponseException extends WebClientException {
|
|||
|
||||
|
||||
/**
|
||||
* Construct a new instance of with the given response data.
|
||||
* @param message the exception message
|
||||
* @param statusCode the raw status code value
|
||||
* @param statusText the status text
|
||||
* @param headers 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})
|
||||
* Constructor with response data only, and a default message.
|
||||
* @since 5.1
|
||||
*/
|
||||
public WebClientResponseException(int statusCode, String statusText,
|
||||
@Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset) {
|
||||
|
||||
this(statusCode + " " + statusText, statusCode, statusText, headers, body, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with a prepared message.
|
||||
*/
|
||||
public WebClientResponseException(String message, int statusCode, String statusText,
|
||||
@Nullable HttpHeaders headers, @Nullable byte[] responseBody,
|
||||
@Nullable Charset responseCharset) {
|
||||
@Nullable HttpHeaders headers, @Nullable byte[] responsebody, @Nullable Charset charset) {
|
||||
|
||||
super(message);
|
||||
|
||||
this.statusCode = statusCode;
|
||||
this.statusText = statusText;
|
||||
this.headers = (headers != null ? headers : HttpHeaders.EMPTY);
|
||||
this.responseBody = (responseBody != null ? responseBody : new byte[0]);
|
||||
this.responseCharset = (responseCharset != null ? responseCharset : StandardCharsets.ISO_8859_1);
|
||||
this.responseBody = (responsebody != null ? responsebody : new byte[0]);
|
||||
this.responseCharset = (charset != null ? charset : StandardCharsets.ISO_8859_1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,4 +114,252 @@ public class WebClientResponseException extends WebClientException {
|
|||
return new String(this.responseBody, this.responseCharset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create {@code WebClientResponseException} or an HTTP status specific sub-class.
|
||||
* @since 5.1
|
||||
*/
|
||||
public static WebClientResponseException create(
|
||||
int statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
|
||||
HttpStatus httpStatus = HttpStatus.resolve(statusCode);
|
||||
if (httpStatus != null) {
|
||||
switch (httpStatus) {
|
||||
case BAD_REQUEST:
|
||||
return new WebClientResponseException.BadRequest(statusText, headers, body, charset);
|
||||
case UNAUTHORIZED:
|
||||
return new WebClientResponseException.Unauthorized(statusText, headers, body, charset);
|
||||
case FORBIDDEN:
|
||||
return new WebClientResponseException.Forbidden(statusText, headers, body, charset);
|
||||
case NOT_FOUND:
|
||||
return new WebClientResponseException.NotFound(statusText, headers, body, charset);
|
||||
case METHOD_NOT_ALLOWED:
|
||||
return new WebClientResponseException.MethodNotAllowed(statusText, headers, body, charset);
|
||||
case NOT_ACCEPTABLE:
|
||||
return new WebClientResponseException.NotAcceptable(statusText, headers, body, charset);
|
||||
case CONFLICT:
|
||||
return new WebClientResponseException.Conflict(statusText, headers, body, charset);
|
||||
case GONE:
|
||||
return new WebClientResponseException.Gone(statusText, headers, body, charset);
|
||||
case UNSUPPORTED_MEDIA_TYPE:
|
||||
return new WebClientResponseException.UnsupportedMediaType(statusText, headers, body, charset);
|
||||
case TOO_MANY_REQUESTS:
|
||||
return new WebClientResponseException.TooManyRequests(statusText, headers, body, charset);
|
||||
case UNPROCESSABLE_ENTITY:
|
||||
return new WebClientResponseException.UnprocessableEntity(statusText, headers, body, charset);
|
||||
case INTERNAL_SERVER_ERROR:
|
||||
return new WebClientResponseException.InternalServerError(statusText, headers, body, charset);
|
||||
case NOT_IMPLEMENTED:
|
||||
return new WebClientResponseException.NotImplemented(statusText, headers, body, charset);
|
||||
case BAD_GATEWAY:
|
||||
return new WebClientResponseException.BadGateway(statusText, headers, body, charset);
|
||||
case SERVICE_UNAVAILABLE:
|
||||
return new WebClientResponseException.ServiceUnavailable(statusText, headers, body, charset);
|
||||
case GATEWAY_TIMEOUT:
|
||||
return new WebClientResponseException.GatewayTimeout(statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
return new WebClientResponseException(statusCode, statusText, headers, body, charset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Sub-classes for specific, client-side, HTTP status codes..
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 400 Bad Request.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class BadRequest extends WebClientResponseException {
|
||||
|
||||
BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.BAD_REQUEST.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 401 Unauthorized.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class Unauthorized extends WebClientResponseException {
|
||||
|
||||
Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.UNAUTHORIZED.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 403 Forbidden.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class Forbidden extends WebClientResponseException {
|
||||
|
||||
Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.FORBIDDEN.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 404 Not Found.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class NotFound extends WebClientResponseException {
|
||||
|
||||
NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.NOT_FOUND.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 405 Method Not Allowed.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class MethodNotAllowed extends WebClientResponseException {
|
||||
|
||||
MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.METHOD_NOT_ALLOWED.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 406 Not Acceptable.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class NotAcceptable extends WebClientResponseException {
|
||||
|
||||
NotAcceptable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.NOT_ACCEPTABLE.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 409 Conflict.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class Conflict extends WebClientResponseException {
|
||||
|
||||
Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.CONFLICT.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 410 Gone.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class Gone extends WebClientResponseException {
|
||||
|
||||
Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.GONE.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 415 Unsupported Media Type.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class UnsupportedMediaType extends WebClientResponseException {
|
||||
|
||||
UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 422 Unprocessable Entity.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class UnprocessableEntity extends WebClientResponseException {
|
||||
|
||||
UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.UNPROCESSABLE_ENTITY.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 429 Too Many Requests.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class TooManyRequests extends WebClientResponseException {
|
||||
|
||||
TooManyRequests(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.TOO_MANY_REQUESTS.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Sub-classes for specific, server-side, HTTP status codes..
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 500 Internal Server Error.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class InternalServerError extends WebClientResponseException {
|
||||
|
||||
InternalServerError(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.INTERNAL_SERVER_ERROR.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 501 Not Implemented.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class NotImplemented extends WebClientResponseException {
|
||||
|
||||
NotImplemented(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.NOT_IMPLEMENTED.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP HTTP 502 Bad Gateway.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class BadGateway extends WebClientResponseException {
|
||||
|
||||
BadGateway(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.BAD_GATEWAY.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 503 Service Unavailable.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class ServiceUnavailable extends WebClientResponseException {
|
||||
|
||||
ServiceUnavailable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.SERVICE_UNAVAILABLE.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebClientResponseException} for status HTTP 504 Gateway Timeout.
|
||||
* @since 5.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class GatewayTimeout extends WebClientResponseException {
|
||||
|
||||
GatewayTimeout(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
|
||||
super(HttpStatus.GATEWAY_TIMEOUT.value(), statusText, headers, body, charset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,8 +60,10 @@ You can also get a stream of objects decoded from the response:
|
|||
.bodyToFlux(Quote.class);
|
||||
----
|
||||
|
||||
By default, responses with 4xx or 5xx status codes result in an error of type
|
||||
`WebClientResponseException` but you can customize that:
|
||||
By default, responses with 4xx or 5xx status codes result in an
|
||||
`WebClientResponseException` or one of its HTTP status specific sub-classes such as
|
||||
`WebClientResponseException.BadRequest`, `WebClientResponseException.NotFound`, and others.
|
||||
You can also use the `onStatus` method to customize the resulting exception:
|
||||
|
||||
[source,java,intent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
Loading…
Reference in New Issue