001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.client; 018 019import java.nio.charset.Charset; 020 021import org.springframework.http.HttpHeaders; 022import org.springframework.http.HttpStatus; 023import org.springframework.lang.Nullable; 024 025/** 026 * Exception thrown when an HTTP 4xx is received. 027 * 028 * @author Arjen Poutsma 029 * @since 3.0 030 * @see DefaultResponseErrorHandler 031 */ 032public class HttpClientErrorException extends HttpStatusCodeException { 033 034 private static final long serialVersionUID = 5177019431887513952L; 035 036 037 /** 038 * Constructor with a status code only. 039 */ 040 public HttpClientErrorException(HttpStatus statusCode) { 041 super(statusCode); 042 } 043 044 /** 045 * Constructor with a status code and status text. 046 */ 047 public HttpClientErrorException(HttpStatus statusCode, String statusText) { 048 super(statusCode, statusText); 049 } 050 051 /** 052 * Constructor with a status code and status text, and content. 053 */ 054 public HttpClientErrorException( 055 HttpStatus statusCode, String statusText, @Nullable byte[] body, @Nullable Charset responseCharset) { 056 057 super(statusCode, statusText, body, responseCharset); 058 } 059 060 /** 061 * Constructor with a status code and status text, headers, and content. 062 */ 063 public HttpClientErrorException(HttpStatus statusCode, String statusText, 064 @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset responseCharset) { 065 066 super(statusCode, statusText, headers, body, responseCharset); 067 } 068 069 /** 070 * Constructor with a status code and status text, headers, and content, 071 * and an prepared message. 072 * @since 5.2.2 073 */ 074 public HttpClientErrorException(String message, HttpStatus statusCode, String statusText, 075 @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset responseCharset) { 076 077 super(message, statusCode, statusText, headers, body, responseCharset); 078 } 079 080 081 /** 082 * Create {@code HttpClientErrorException} or an HTTP status specific sub-class. 083 * @since 5.1 084 */ 085 public static HttpClientErrorException create( 086 HttpStatus statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 087 088 return create(null, statusCode, statusText, headers, body, charset); 089 } 090 091 /** 092 * Variant of {@link #create(HttpStatus, String, HttpHeaders, byte[], Charset)} 093 * with an optional prepared message. 094 * @since 5.2.2 095 */ 096 public static HttpClientErrorException create(@Nullable String message, HttpStatus statusCode, 097 String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 098 099 switch (statusCode) { 100 case BAD_REQUEST: 101 return message != null ? 102 new HttpClientErrorException.BadRequest(message, statusText, headers, body, charset) : 103 new HttpClientErrorException.BadRequest(statusText, headers, body, charset); 104 case UNAUTHORIZED: 105 return message != null ? 106 new HttpClientErrorException.Unauthorized(message, statusText, headers, body, charset) : 107 new HttpClientErrorException.Unauthorized(statusText, headers, body, charset); 108 case FORBIDDEN: 109 return message != null ? 110 new HttpClientErrorException.Forbidden(message, statusText, headers, body, charset) : 111 new HttpClientErrorException.Forbidden(statusText, headers, body, charset); 112 case NOT_FOUND: 113 return message != null ? 114 new HttpClientErrorException.NotFound(message, statusText, headers, body, charset) : 115 new HttpClientErrorException.NotFound(statusText, headers, body, charset); 116 case METHOD_NOT_ALLOWED: 117 return message != null ? 118 new HttpClientErrorException.MethodNotAllowed(message, statusText, headers, body, charset) : 119 new HttpClientErrorException.MethodNotAllowed(statusText, headers, body, charset); 120 case NOT_ACCEPTABLE: 121 return message != null ? 122 new HttpClientErrorException.NotAcceptable(message, statusText, headers, body, charset) : 123 new HttpClientErrorException.NotAcceptable(statusText, headers, body, charset); 124 case CONFLICT: 125 return message != null ? 126 new HttpClientErrorException.Conflict(message, statusText, headers, body, charset) : 127 new HttpClientErrorException.Conflict(statusText, headers, body, charset); 128 case GONE: 129 return message != null ? 130 new HttpClientErrorException.Gone(message, statusText, headers, body, charset) : 131 new HttpClientErrorException.Gone(statusText, headers, body, charset); 132 case UNSUPPORTED_MEDIA_TYPE: 133 return message != null ? 134 new HttpClientErrorException.UnsupportedMediaType(message, statusText, headers, body, charset) : 135 new HttpClientErrorException.UnsupportedMediaType(statusText, headers, body, charset); 136 case TOO_MANY_REQUESTS: 137 return message != null ? 138 new HttpClientErrorException.TooManyRequests(message, statusText, headers, body, charset) : 139 new HttpClientErrorException.TooManyRequests(statusText, headers, body, charset); 140 case UNPROCESSABLE_ENTITY: 141 return message != null ? 142 new HttpClientErrorException.UnprocessableEntity(message, statusText, headers, body, charset) : 143 new HttpClientErrorException.UnprocessableEntity(statusText, headers, body, charset); 144 default: 145 return message != null ? 146 new HttpClientErrorException(message, statusCode, statusText, headers, body, charset) : 147 new HttpClientErrorException(statusCode, statusText, headers, body, charset); 148 } 149 } 150 151 152 // Subclasses for specific HTTP status codes 153 154 /** 155 * {@link HttpClientErrorException} for status HTTP 400 Bad Request. 156 * @since 5.1 157 */ 158 @SuppressWarnings("serial") 159 public static final class BadRequest extends HttpClientErrorException { 160 161 private BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 162 super(HttpStatus.BAD_REQUEST, statusText, headers, body, charset); 163 } 164 165 private BadRequest(String message, String statusText, 166 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 167 168 super(message, HttpStatus.BAD_REQUEST, statusText, headers, body, charset); 169 } 170 } 171 172 /** 173 * {@link HttpClientErrorException} for status HTTP 401 Unauthorized. 174 * @since 5.1 175 */ 176 @SuppressWarnings("serial") 177 public static final class Unauthorized extends HttpClientErrorException { 178 179 private Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 180 super(HttpStatus.UNAUTHORIZED, statusText, headers, body, charset); 181 } 182 183 private Unauthorized(String message, String statusText, 184 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 185 186 super(message, HttpStatus.UNAUTHORIZED, statusText, headers, body, charset); 187 } 188 } 189 190 /** 191 * {@link HttpClientErrorException} for status HTTP 403 Forbidden. 192 * @since 5.1 193 */ 194 @SuppressWarnings("serial") 195 public static final class Forbidden extends HttpClientErrorException { 196 197 private Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 198 super(HttpStatus.FORBIDDEN, statusText, headers, body, charset); 199 } 200 201 private Forbidden(String message, String statusText, 202 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 203 204 super(message, HttpStatus.FORBIDDEN, statusText, headers, body, charset); 205 } 206 } 207 208 /** 209 * {@link HttpClientErrorException} for status HTTP 404 Not Found. 210 * @since 5.1 211 */ 212 @SuppressWarnings("serial") 213 public static final class NotFound extends HttpClientErrorException { 214 215 private NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 216 super(HttpStatus.NOT_FOUND, statusText, headers, body, charset); 217 } 218 219 private NotFound(String message, String statusText, 220 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 221 222 super(message, HttpStatus.NOT_FOUND, statusText, headers, body, charset); 223 } 224 } 225 226 /** 227 * {@link HttpClientErrorException} for status HTTP 405 Method Not Allowed. 228 * @since 5.1 229 */ 230 @SuppressWarnings("serial") 231 public static final class MethodNotAllowed extends HttpClientErrorException { 232 233 private MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 234 super(HttpStatus.METHOD_NOT_ALLOWED, statusText, headers, body, charset); 235 } 236 237 private MethodNotAllowed(String message, String statusText, 238 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 239 240 super(message, HttpStatus.METHOD_NOT_ALLOWED, statusText, headers, body, charset); 241 } 242 } 243 244 /** 245 * {@link HttpClientErrorException} for status HTTP 406 Not Acceptable. 246 * @since 5.1 247 */ 248 @SuppressWarnings("serial") 249 public static final class NotAcceptable extends HttpClientErrorException { 250 251 private NotAcceptable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 252 super(HttpStatus.NOT_ACCEPTABLE, statusText, headers, body, charset); 253 } 254 255 private NotAcceptable(String message, String statusText, 256 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 257 258 super(message, HttpStatus.NOT_ACCEPTABLE, statusText, headers, body, charset); 259 } 260 } 261 262 /** 263 * {@link HttpClientErrorException} for status HTTP 409 Conflict. 264 * @since 5.1 265 */ 266 @SuppressWarnings("serial") 267 public static final class Conflict extends HttpClientErrorException { 268 269 private Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 270 super(HttpStatus.CONFLICT, statusText, headers, body, charset); 271 } 272 273 private Conflict(String message, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 274 super(message, HttpStatus.CONFLICT, statusText, headers, body, charset); 275 } 276 } 277 278 /** 279 * {@link HttpClientErrorException} for status HTTP 410 Gone. 280 * @since 5.1 281 */ 282 @SuppressWarnings("serial") 283 public static final class Gone extends HttpClientErrorException { 284 285 private Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 286 super(HttpStatus.GONE, statusText, headers, body, charset); 287 } 288 289 private Gone(String message, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 290 super(message, HttpStatus.GONE, statusText, headers, body, charset); 291 } 292 } 293 294 /** 295 * {@link HttpClientErrorException} for status HTTP 415 Unsupported Media Type. 296 * @since 5.1 297 */ 298 @SuppressWarnings("serial") 299 public static final class UnsupportedMediaType extends HttpClientErrorException { 300 301 private UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 302 super(HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, headers, body, charset); 303 } 304 305 private UnsupportedMediaType(String message, String statusText, 306 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 307 308 super(message, HttpStatus.UNSUPPORTED_MEDIA_TYPE, statusText, headers, body, charset); 309 } 310 } 311 312 /** 313 * {@link HttpClientErrorException} for status HTTP 422 Unprocessable Entity. 314 * @since 5.1 315 */ 316 @SuppressWarnings("serial") 317 public static final class UnprocessableEntity extends HttpClientErrorException { 318 319 private UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 320 super(HttpStatus.UNPROCESSABLE_ENTITY, statusText, headers, body, charset); 321 } 322 323 private UnprocessableEntity(String message, String statusText, 324 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 325 326 super(message, HttpStatus.UNPROCESSABLE_ENTITY, statusText, headers, body, charset); 327 } 328 } 329 330 /** 331 * {@link HttpClientErrorException} for status HTTP 429 Too Many Requests. 332 * @since 5.1 333 */ 334 @SuppressWarnings("serial") 335 public static final class TooManyRequests extends HttpClientErrorException { 336 337 private TooManyRequests(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { 338 super(HttpStatus.TOO_MANY_REQUESTS, statusText, headers, body, charset); 339 } 340 341 private TooManyRequests(String message, String statusText, 342 HttpHeaders headers, byte[] body, @Nullable Charset charset) { 343 344 super(message, HttpStatus.TOO_MANY_REQUESTS, statusText, headers, body, charset); 345 } 346 } 347 348}