From 28ac0d3883e0c683fb995dffc0af7c8a82f3c3d0 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 17 Mar 2022 14:21:04 +0100 Subject: [PATCH] Use HttpStatusCode interface This commit contains changes made because of the introduction of HttpStatusCode. In general, methods that used to return a HttpStatus now return HttpStatusCode instead, and methods that returned raw status codes are now deprecated. See gh-28214 --- .../http/client/MockClientHttpResponse.java | 44 +++---- .../reactive/MockClientHttpResponse.java | 31 ++--- .../MockMvcClientHttpRequestFactory.java | 3 +- .../response/DefaultResponseCreator.java | 14 +-- .../response/MockRestResponseCreators.java | 5 +- .../web/reactive/server/ExchangeResult.java | 21 +++- .../reactive/server/HttpHandlerConnector.java | 6 +- .../web/reactive/server/StatusAssertions.java | 38 ++++--- .../servlet/result/StatusResultMatchers.java | 7 +- .../response/ResponseCreatorsTests.java | 3 +- .../springframework/http/ProblemDetail.java | 24 ++-- .../springframework/http/ResponseEntity.java | 34 +++--- .../client/AbstractClientHttpResponse.java | 8 +- .../BufferingClientHttpResponseWrapper.java | 5 +- .../http/client/ClientHttpResponse.java | 19 ++-- .../HttpComponentsClientHttpResponse.java | 9 +- .../client/OkHttp3ClientHttpResponse.java | 9 +- .../http/client/SimpleClientHttpResponse.java | 9 +- .../client/reactive/ClientHttpResponse.java | 17 ++- .../reactive/ClientHttpResponseDecorator.java | 5 +- .../HttpComponentsClientHttpResponse.java | 7 +- .../reactive/JdkClientHttpResponse.java | 7 +- .../reactive/JettyClientHttpResponse.java | 7 +- .../reactive/ReactorClientHttpResponse.java | 7 +- .../server/DelegatingServerHttpResponse.java | 4 +- .../http/server/ServerHttpResponse.java | 4 +- .../server/ServletServerHttpResponse.java | 4 +- .../reactive/AbstractServerHttpResponse.java | 23 ++-- .../reactive/ReactorServerHttpResponse.java | 13 ++- .../server/reactive/ServerHttpResponse.java | 30 ++--- .../reactive/ServerHttpResponseDecorator.java | 7 +- .../reactive/ServletServerHttpResponse.java | 13 ++- .../reactive/UndertowServerHttpResponse.java | 13 ++- .../springframework/web/ErrorResponse.java | 15 +-- .../web/ErrorResponseException.java | 32 ++---- .../web/HttpMediaTypeException.java | 2 +- .../HttpMediaTypeNotAcceptableException.java | 5 +- .../HttpMediaTypeNotSupportedException.java | 5 +- ...ttpRequestMethodNotSupportedException.java | 7 +- .../bind/MethodArgumentNotValidException.java | 8 +- .../bind/MissingPathVariableException.java | 6 +- .../bind/ServletRequestBindingException.java | 8 +- .../client/DefaultResponseErrorHandler.java | 61 +++++----- .../ExtractingResponseErrorHandler.java | 19 ++-- .../web/client/HttpClientErrorException.java | 107 +++++++++--------- .../client/HttpMessageConverterExtractor.java | 2 +- .../web/client/HttpServerErrorException.java | 72 +++++++----- .../web/client/HttpStatusCodeException.java | 53 +++++---- .../MessageBodyClientHttpResponseWrapper.java | 10 +- .../client/RestClientResponseException.java | 32 +++++- .../web/client/RestTemplate.java | 11 +- .../client/UnknownContentTypeException.java | 34 +++++- .../UnknownHttpStatusCodeException.java | 9 +- .../async/AsyncRequestTimeoutException.java | 7 +- .../web/filter/RelativeRedirectFilter.java | 7 +- .../RelativeRedirectResponseWrapper.java | 8 +- .../web/method/HandlerMethod.java | 6 +- .../method/support/ModelAndViewContainer.java | 8 +- .../web/server/ResponseStatusException.java | 33 +++--- .../adapter/DefaultServerWebExchange.java | 3 +- .../server/adapter/HttpWebHandlerAdapter.java | 3 +- .../ResponseStatusExceptionHandler.java | 31 ++--- .../web/ErrorResponseExceptionTests.java | 2 +- ...ltResponseErrorHandlerHttpStatusTests.java | 4 +- .../DefaultResponseErrorHandlerTests.java | 57 +++++----- .../ExtractingResponseErrorHandlerTests.java | 20 ++-- .../HttpMessageConverterExtractorTests.java | 24 ++-- .../reactive/MockClientHttpResponse.java | 31 ++--- .../function/client/ClientResponse.java | 25 ++-- .../client/DefaultClientResponse.java | 9 +- .../client/DefaultClientResponseBuilder.java | 26 +++-- .../function/client/DefaultWebClient.java | 40 ++++--- .../client/ExchangeFilterFunctions.java | 6 +- .../function/client/ExchangeFunctions.java | 9 +- .../UnknownHttpStatusCodeException.java | 14 +++ .../reactive/function/client/WebClient.java | 4 +- .../client/WebClientResponseException.java | 51 +++++++-- .../function/client/WebClientUtils.java | 4 +- .../client/support/ClientResponseWrapper.java | 5 +- .../server/DefaultEntityResponseBuilder.java | 14 +-- .../DefaultRenderingResponseBuilder.java | 17 ++- .../function/server/DefaultServerRequest.java | 6 +- .../server/DefaultServerResponseBuilder.java | 36 +++--- .../function/server/EntityResponse.java | 4 +- .../function/server/RenderingResponse.java | 4 +- .../function/server/ServerResponse.java | 17 ++- ...WebFluxResponseStatusExceptionHandler.java | 11 +- .../result/method/InvocableHandlerMethod.java | 4 +- .../AbstractMessageWriterResultHandler.java | 4 +- .../ResponseEntityResultHandler.java | 7 +- .../result/view/DefaultRendering.java | 8 +- .../result/view/DefaultRenderingBuilder.java | 6 +- .../reactive/result/view/RedirectView.java | 9 +- .../web/reactive/result/view/Rendering.java | 6 +- .../view/ViewResolutionResultHandler.java | 6 +- .../function/server/CoRouterFunctionDsl.kt | 4 +- .../function/server/RouterFunctionDsl.kt | 3 +- .../DefaultClientResponseBuilderTests.java | 4 +- .../client/DefaultClientResponseTests.java | 14 +-- .../client/DefaultWebClientTests.java | 10 +- .../client/ExchangeFilterFunctionsTests.java | 5 +- .../client/WebClientIntegrationTests.java | 13 ++- .../server/RouterFunctionBuilderTests.java | 47 ++++---- .../DispatcherHandlerIntegrationTests.java | 3 +- .../resource/ResourceWebHandlerTests.java | 12 +- ...pingExceptionHandlingIntegrationTests.java | 3 +- .../result/view/ZeroDemandResponse.java | 6 +- .../web/servlet/FrameworkServlet.java | 6 +- .../web/servlet/ModelAndView.java | 12 +- .../web/servlet/NoHandlerFoundException.java | 8 +- .../ViewControllerBeanDefinitionParser.java | 8 +- .../RedirectViewControllerRegistration.java | 4 +- .../ViewControllerRegistration.java | 4 +- .../annotation/ViewControllerRegistry.java | 4 +- .../function/AbstractServerResponse.java | 15 +-- .../function/DefaultAsyncServerResponse.java | 5 +- .../DefaultEntityResponseBuilder.java | 18 +-- .../DefaultRenderingResponseBuilder.java | 26 ++--- .../DefaultServerResponseBuilder.java | 19 ++-- .../web/servlet/function/EntityResponse.java | 4 +- .../servlet/function/RenderingResponse.java | 4 +- .../web/servlet/function/ServerResponse.java | 17 ++- .../servlet/function/SseServerResponse.java | 3 +- .../mvc/ParameterizableViewController.java | 7 +- .../ResponseStatusExceptionResolver.java | 2 +- .../ExceptionHandlerExceptionResolver.java | 4 +- .../annotation/HttpEntityMethodProcessor.java | 4 +- ...ResponseBodyEmitterReturnValueHandler.java | 5 +- .../ResponseEntityExceptionHandler.java | 86 +++++++------- .../ServletInvocableHandlerMethod.java | 4 +- ...reamingResponseBodyReturnValueHandler.java | 5 +- .../DefaultHandlerExceptionResolver.java | 2 +- .../web/servlet/view/RedirectView.java | 15 +-- .../web/servlet/function/RouterFunctionDsl.kt | 4 +- .../function/RouterFunctionBuilderTests.java | 11 +- .../ResponseEntityExceptionHandlerTests.java | 3 +- .../sockjs/client/JettyXhrTransport.java | 6 +- .../client/RestTemplateXhrTransport.java | 10 +- .../sockjs/client/UndertowXhrTransport.java | 6 +- .../TransportHandlingSockJsService.java | 7 +- ...AbstractHttpReceivingTransportHandler.java | 3 +- .../handler/XhrReceivingTransportHandler.java | 3 +- .../client/RestTemplateXhrTransportTests.java | 2 +- 143 files changed, 1064 insertions(+), 950 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpResponse.java b/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpResponse.java index c8450ca0be..b8a5d084c1 100644 --- a/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/http/client/MockClientHttpResponse.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.ClientHttpResponse; import org.springframework.mock.http.MockHttpInputMessage; import org.springframework.util.Assert; @@ -32,62 +33,65 @@ import org.springframework.util.Assert; */ public class MockClientHttpResponse extends MockHttpInputMessage implements ClientHttpResponse { - private final int statusCode; + private final HttpStatusCode statusCode; /** * Constructor with response body as a byte array. */ - public MockClientHttpResponse(byte[] body, HttpStatus statusCode) { + public MockClientHttpResponse(byte[] body, HttpStatusCode statusCode) { super(body); - Assert.notNull(statusCode, "HttpStatus is required"); - this.statusCode = statusCode.value(); + Assert.notNull(statusCode, "HttpStatusCode is required"); + this.statusCode = statusCode; } /** - * Variant of {@link #MockClientHttpResponse(byte[], HttpStatus)} with a + * Variant of {@link #MockClientHttpResponse(byte[], HttpStatusCode)} with a * custom HTTP status code. * @since 5.3.17 */ public MockClientHttpResponse(byte[] body, int statusCode) { - super(body); - this.statusCode = statusCode; + this(body, HttpStatusCode.valueOf(statusCode)); } /** * Constructor with response body as InputStream. */ - public MockClientHttpResponse(InputStream body, HttpStatus statusCode) { + public MockClientHttpResponse(InputStream body, HttpStatusCode statusCode) { super(body); Assert.notNull(statusCode, "HttpStatus is required"); - this.statusCode = statusCode.value(); + this.statusCode = statusCode; } /** - * Variant of {@link #MockClientHttpResponse(InputStream, HttpStatus)} with a + * Variant of {@link #MockClientHttpResponse(InputStream, HttpStatusCode)} with a * custom HTTP status code. * @since 5.3.17 */ public MockClientHttpResponse(InputStream body, int statusCode) { - super(body); - this.statusCode = statusCode; + this(body, HttpStatusCode.valueOf(statusCode)); } @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.statusCode); - } - - @Override - public int getRawStatusCode() { + public HttpStatusCode getStatusCode() { return this.statusCode; } + @Override + @Deprecated + public int getRawStatusCode() { + return this.statusCode.value(); + } + @Override public String getStatusText() { - HttpStatus status = HttpStatus.resolve(this.statusCode); - return (status != null ? status.getReasonPhrase() : ""); + if (this.statusCode instanceof HttpStatus status) { + return status.getReasonPhrase(); + } + else { + return ""; + } } @Override diff --git a/spring-test/src/main/java/org/springframework/mock/http/client/reactive/MockClientHttpResponse.java b/spring-test/src/main/java/org/springframework/mock/http/client/reactive/MockClientHttpResponse.java index c2e950025f..85de0e70a7 100644 --- a/spring-test/src/main/java/org/springframework/mock/http/client/reactive/MockClientHttpResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/http/client/reactive/MockClientHttpResponse.java @@ -30,6 +30,7 @@ import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.client.reactive.ClientHttpResponse; @@ -46,7 +47,7 @@ import org.springframework.util.MultiValueMap; */ public class MockClientHttpResponse implements ClientHttpResponse { - private final int status; + private final HttpStatusCode statusCode; private final HttpHeaders headers = new HttpHeaders(); @@ -55,25 +56,25 @@ public class MockClientHttpResponse implements ClientHttpResponse { private Flux body = Flux.empty(); - public MockClientHttpResponse(HttpStatus status) { - Assert.notNull(status, "HttpStatus is required"); - this.status = status.value(); - } - public MockClientHttpResponse(int status) { - Assert.isTrue(status > 99 && status < 1000, "Status must be between 100 and 999"); - this.status = status; + this(HttpStatusCode.valueOf(status)); + } + + public MockClientHttpResponse(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode is required"); + this.statusCode = status; } @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.status); + public HttpStatusCode getStatusCode() { + return this.statusCode; } @Override + @Deprecated public int getRawStatusCode() { - return this.status; + return this.statusCode.value(); } @Override @@ -140,7 +141,11 @@ public class MockClientHttpResponse implements ClientHttpResponse { @Override public String toString() { - HttpStatus code = HttpStatus.resolve(this.status); - return (code != null ? code.name() + "(" + this.status + ")" : "Status (" + this.status + ")") + this.headers; + if (this.statusCode instanceof HttpStatus status) { + return status.name() + "(" + this.statusCode + ")" + this.headers; + } + else { + return "Status (" + this.statusCode + ")" + this.headers; + } } } diff --git a/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java b/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java index 4c4592230d..b64472c9b4 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java @@ -23,6 +23,7 @@ import java.util.List; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; @@ -71,7 +72,7 @@ public class MockMvcClientHttpRequestFactory implements ClientHttpRequestFactory .andReturn() .getResponse(); - HttpStatus status = HttpStatus.valueOf(servletResponse.getStatus()); + HttpStatusCode status = HttpStatusCode.valueOf(servletResponse.getStatus()); byte[] body = servletResponse.getContentAsByteArray(); MockClientHttpResponse clientResponse = new MockClientHttpResponse(body, status); clientResponse.getHeaders().putAll(getResponseHeaders(servletResponse)); diff --git a/spring-test/src/main/java/org/springframework/test/web/client/response/DefaultResponseCreator.java b/spring-test/src/main/java/org/springframework/test/web/client/response/DefaultResponseCreator.java index 001b33e053..081001fe8a 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/response/DefaultResponseCreator.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/response/DefaultResponseCreator.java @@ -22,7 +22,7 @@ import java.nio.charset.StandardCharsets; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; @@ -39,7 +39,7 @@ import org.springframework.util.Assert; */ public class DefaultResponseCreator implements ResponseCreator { - private final int statusCode; + private final HttpStatusCode statusCode; private byte[] content = new byte[0]; @@ -52,18 +52,18 @@ public class DefaultResponseCreator implements ResponseCreator { /** * Protected constructor. * Use static factory methods in {@link MockRestResponseCreators}. + * @since 5.3.17 */ - protected DefaultResponseCreator(HttpStatus statusCode) { - Assert.notNull(statusCode, "HttpStatus must not be null"); - this.statusCode = statusCode.value(); + protected DefaultResponseCreator(int statusCode) { + this(HttpStatusCode.valueOf(statusCode)); } /** * Protected constructor. * Use static factory methods in {@link MockRestResponseCreators}. - * @since 5.3.17 */ - protected DefaultResponseCreator(int statusCode) { + protected DefaultResponseCreator(HttpStatusCode statusCode) { + Assert.notNull(statusCode, "HttpStatusCode must not be null"); this.statusCode = statusCode; } diff --git a/spring-test/src/main/java/org/springframework/test/web/client/response/MockRestResponseCreators.java b/spring-test/src/main/java/org/springframework/test/web/client/response/MockRestResponseCreators.java index 73712ea5d8..6c3a5b2ac1 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/response/MockRestResponseCreators.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/response/MockRestResponseCreators.java @@ -21,6 +21,7 @@ import java.net.URI; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.test.web.client.ResponseCreator; @@ -113,12 +114,12 @@ public abstract class MockRestResponseCreators { * {@code ResponseCreator} with a specific HTTP status. * @param status the response status */ - public static DefaultResponseCreator withStatus(HttpStatus status) { + public static DefaultResponseCreator withStatus(HttpStatusCode status) { return new DefaultResponseCreator(status); } /** - * Variant of {@link #withStatus(HttpStatus)} for a custom HTTP status code. + * Variant of {@link #withStatus(HttpStatusCode)} with an integer. * @param status the response status * @since 5.3.17 */ diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java index e44c3b9f06..301a5afd7c 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java @@ -31,6 +31,7 @@ import reactor.core.publisher.Mono; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.client.reactive.ClientHttpRequest; @@ -170,17 +171,18 @@ public class ExchangeResult { /** - * Return the HTTP status code as an {@link HttpStatus} enum value. + * Return the HTTP status code as an {@link HttpStatusCode} value. */ - public HttpStatus getStatus() { + public HttpStatusCode getStatus() { return this.response.getStatusCode(); } /** - * Return the HTTP status code (potentially non-standard and not resolvable - * through the {@link HttpStatus} enum) as an integer. + * Return the HTTP status code as an integer. * @since 5.1.10 + * @deprecated as of 6.0, in favor of {@link #getStatus()} */ + @Deprecated public int getRawStatusCode() { return this.response.getRawStatusCode(); } @@ -248,13 +250,22 @@ public class ExchangeResult { "\n" + formatBody(getRequestHeaders().getContentType(), this.requestBody) + "\n" + "\n" + - "< " + getStatus() + " " + getStatus().getReasonPhrase() + "\n" + + "< " + getStatus() + " " + getReasonPhrase(getStatus()) + "\n" + "< " + formatHeaders(getResponseHeaders(), "\n< ") + "\n" + "\n" + formatBody(getResponseHeaders().getContentType(), this.responseBody) +"\n" + formatMockServerResult(); } + private static String getReasonPhrase(HttpStatusCode statusCode) { + if (statusCode instanceof HttpStatus status) { + return status.getReasonPhrase(); + } + else { + return ""; + } + } + private String formatHeaders(HttpHeaders headers, String delimiter) { return headers.entrySet().stream() .map(entry -> entry.getKey() + ": " + entry.getValue()) diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/HttpHandlerConnector.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/HttpHandlerConnector.java index 2db4fdc7d9..92df11075d 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/HttpHandlerConnector.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/HttpHandlerConnector.java @@ -31,6 +31,8 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpCookie; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ClientHttpRequest; import org.springframework.http.client.reactive.ClientHttpResponse; @@ -142,8 +144,8 @@ public class HttpHandlerConnector implements ClientHttpConnector { } private ClientHttpResponse adaptResponse(MockServerHttpResponse response, Flux body) { - Integer status = response.getRawStatusCode(); - MockClientHttpResponse clientResponse = new MockClientHttpResponse((status != null) ? status : 200); + HttpStatusCode status = response.getStatusCode(); + MockClientHttpResponse clientResponse = new MockClientHttpResponse((status != null) ? status : HttpStatus.OK); clientResponse.getHeaders().putAll(response.getHeaders()); clientResponse.getCookies().putAll(response.getCookies()); clientResponse.setBody(body); diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java index 5c3641e31b..d0649473b5 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/StatusAssertions.java @@ -22,6 +22,7 @@ import org.hamcrest.Matcher; import org.hamcrest.MatcherAssert; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.test.util.AssertionErrors; /** @@ -45,19 +46,19 @@ public class StatusAssertions { /** - * Assert the response status as an {@link HttpStatus}. + * Assert the response status as an {@link HttpStatusCode}. */ - public WebTestClient.ResponseSpec isEqualTo(HttpStatus status) { - return isEqualTo(status.value()); + public WebTestClient.ResponseSpec isEqualTo(HttpStatusCode status) { + HttpStatusCode actual = this.exchangeResult.getStatus(); + this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.assertEquals("Status", status, actual)); + return this.responseSpec; } /** * Assert the response status as an integer. */ public WebTestClient.ResponseSpec isEqualTo(int status) { - int actual = this.exchangeResult.getRawStatusCode(); - this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.assertEquals("Status", status, actual)); - return this.responseSpec; + return isEqualTo(HttpStatusCode.valueOf(status)); } /** @@ -156,12 +157,22 @@ public class StatusAssertions { * Assert the response error message. */ public WebTestClient.ResponseSpec reasonEquals(String reason) { - String actual = this.exchangeResult.getStatus().getReasonPhrase(); + String actual = getReasonPhrase(this.exchangeResult.getStatus()); this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.assertEquals("Response status reason", reason, actual)); return this.responseSpec; } + private static String getReasonPhrase(HttpStatusCode statusCode) { + if (statusCode instanceof HttpStatus status) { + return status.getReasonPhrase(); + } + else { + return ""; + } + } + + /** * Assert the response status code is in the 1xx range. */ @@ -203,7 +214,7 @@ public class StatusAssertions { * @since 5.1 */ public WebTestClient.ResponseSpec value(Matcher matcher) { - int actual = this.exchangeResult.getRawStatusCode(); + int actual = this.exchangeResult.getStatus().value(); this.exchangeResult.assertWithDiagnostics(() -> MatcherAssert.assertThat("Response status", actual, matcher)); return this.responseSpec; } @@ -214,22 +225,23 @@ public class StatusAssertions { * @since 5.1 */ public WebTestClient.ResponseSpec value(Consumer consumer) { - int actual = this.exchangeResult.getRawStatusCode(); + int actual = this.exchangeResult.getStatus().value(); this.exchangeResult.assertWithDiagnostics(() -> consumer.accept(actual)); return this.responseSpec; } - private WebTestClient.ResponseSpec assertStatusAndReturn(HttpStatus expected) { - HttpStatus actual = this.exchangeResult.getStatus(); + private WebTestClient.ResponseSpec assertStatusAndReturn(HttpStatusCode expected) { + HttpStatusCode actual = this.exchangeResult.getStatus(); this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.assertEquals("Status", expected, actual)); return this.responseSpec; } private WebTestClient.ResponseSpec assertSeriesAndReturn(HttpStatus.Series expected) { - HttpStatus status = this.exchangeResult.getStatus(); + HttpStatusCode status = this.exchangeResult.getStatus(); + HttpStatus.Series series = HttpStatus.Series.resolve(status.value()); this.exchangeResult.assertWithDiagnostics(() -> - AssertionErrors.assertEquals("Range for response status value " + status, expected, status.series())); + AssertionErrors.assertEquals("Range for response status value " + status, expected, series)); return this.responseSpec; } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/StatusResultMatchers.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/StatusResultMatchers.java index 6983b68660..9c2b01e942 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/StatusResultMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/StatusResultMatchers.java @@ -19,6 +19,7 @@ package org.springframework.test.web.servlet.result; import org.hamcrest.Matcher; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.ResultMatcher; @@ -104,9 +105,7 @@ public class StatusResultMatchers { } private HttpStatus.Series getHttpStatusSeries(MvcResult result) { - int statusValue = result.getResponse().getStatus(); - HttpStatus status = HttpStatus.valueOf(statusValue); - return status.series(); + return HttpStatus.Series.resolve(result.getResponse().getStatus()); } /** @@ -623,7 +622,7 @@ public class StatusResultMatchers { /** * Match the expected response status to that of the HttpServletResponse. */ - private ResultMatcher matcher(HttpStatus status) { + private ResultMatcher matcher(HttpStatusCode status) { return result -> assertEquals("Status", status.value(), result.getResponse().getStatus()); } diff --git a/spring-test/src/test/java/org/springframework/test/web/client/response/ResponseCreatorsTests.java b/spring-test/src/test/java/org/springframework/test/web/client/response/ResponseCreatorsTests.java index a6d5f4e904..ba50da304f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/response/ResponseCreatorsTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/response/ResponseCreatorsTests.java @@ -22,6 +22,7 @@ import java.net.URI; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.mock.http.client.MockClientHttpResponse; import org.springframework.test.web.client.ResponseCreator; @@ -133,7 +134,7 @@ class ResponseCreatorsTests { DefaultResponseCreator responseCreator = MockRestResponseCreators.withRawStatus(454); MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null); - assertThat(response.getRawStatusCode()).isEqualTo(454); + assertThat(response.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(454)); assertThat(response.getStatusText()).isEmpty(); } diff --git a/spring-web/src/main/java/org/springframework/http/ProblemDetail.java b/spring-web/src/main/java/org/springframework/http/ProblemDetail.java index 216361586b..ad7fe2674a 100644 --- a/spring-web/src/main/java/org/springframework/http/ProblemDetail.java +++ b/spring-web/src/main/java/org/springframework/http/ProblemDetail.java @@ -55,7 +55,7 @@ public class ProblemDetail { /** * Protected constructor for subclasses. *

To create a {@link ProblemDetail} instance, use static factory methods, - * {@link #forStatus(HttpStatus)} or {@link #forRawStatusCode(int)}. + * {@link #forStatus(HttpStatusCode)} or {@link #forStatus(int)}. * @param rawStatusCode the response status to use */ protected ProblemDetail(int rawStatusCode) { @@ -97,12 +97,12 @@ public class ProblemDetail { /** * Variant of {@link #setStatus(int)} for chained initialization. - * @param status the response status for the problem + * @param statusCode the response status for the problem * @return the same instance */ - public ProblemDetail withStatus(HttpStatus status) { - Assert.notNull(status, "HttpStatus is required"); - setStatus(status.value()); + public ProblemDetail withStatus(HttpStatusCode statusCode) { + Assert.notNull(statusCode, "HttpStatus is required"); + setStatus(statusCode.value()); return this; } @@ -111,7 +111,7 @@ public class ProblemDetail { * @param status the response status value for the problem * @return the same instance */ - public ProblemDetail withRawStatusCode(int status) { + public ProblemDetail withStatus(int status) { setStatus(status); return this; } @@ -164,8 +164,8 @@ public class ProblemDetail { /** * Setter for the {@link #getStatus() problem status}. * @param status the problem status - * @see #withStatus(HttpStatus) - * @see #withRawStatusCode(int) + * @see #withStatus(HttpStatusCode) + * @see #withStatus(int) */ public void setStatus(int status) { this.status = status; @@ -264,15 +264,15 @@ public class ProblemDetail { /** * Create a {@code ProblemDetail} instance with the given status code. */ - public static ProblemDetail forStatus(HttpStatus status) { - Assert.notNull(status, "HttpStatus is required"); - return forRawStatusCode(status.value()); + public static ProblemDetail forStatus(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode is required"); + return forStatus(status.value()); } /** * Create a {@code ProblemDetail} instance with the given status value. */ - public static ProblemDetail forRawStatusCode(int status) { + public static ProblemDetail forStatus(int status) { return new ProblemDetail(status); } diff --git a/spring-web/src/main/java/org/springframework/http/ResponseEntity.java b/spring-web/src/main/java/org/springframework/http/ResponseEntity.java index dc1ec11a97..95c1071b21 100644 --- a/spring-web/src/main/java/org/springframework/http/ResponseEntity.java +++ b/spring-web/src/main/java/org/springframework/http/ResponseEntity.java @@ -31,7 +31,7 @@ import org.springframework.util.MultiValueMap; import org.springframework.util.ObjectUtils; /** - * Extension of {@link HttpEntity} that adds an {@link HttpStatus} status code. + * Extension of {@link HttpEntity} that adds an {@link HttpStatusCode} status code. * Used in {@code RestTemplate} as well as in {@code @Controller} methods. * *

In {@code RestTemplate}, this class is returned by @@ -85,7 +85,7 @@ public class ResponseEntity extends HttpEntity { * Create a {@code ResponseEntity} with a status code only. * @param status the status code */ - public ResponseEntity(HttpStatus status) { + public ResponseEntity(HttpStatusCode status) { this(null, null, status); } @@ -94,7 +94,7 @@ public class ResponseEntity extends HttpEntity { * @param body the entity body * @param status the status code */ - public ResponseEntity(@Nullable T body, HttpStatus status) { + public ResponseEntity(@Nullable T body, HttpStatusCode status) { this(body, null, status); } @@ -103,7 +103,7 @@ public class ResponseEntity extends HttpEntity { * @param headers the entity headers * @param status the status code */ - public ResponseEntity(MultiValueMap headers, HttpStatus status) { + public ResponseEntity(MultiValueMap headers, HttpStatusCode status) { this(null, headers, status); } @@ -113,7 +113,7 @@ public class ResponseEntity extends HttpEntity { * @param headers the entity headers * @param status the status code */ - public ResponseEntity(@Nullable T body, @Nullable MultiValueMap headers, HttpStatus status) { + public ResponseEntity(@Nullable T body, @Nullable MultiValueMap headers, HttpStatusCode status) { this(body, headers, (Object) status); } @@ -133,7 +133,7 @@ public class ResponseEntity extends HttpEntity { */ private ResponseEntity(@Nullable T body, @Nullable MultiValueMap headers, Object status) { super(body, headers); - Assert.notNull(status, "HttpStatus must not be null"); + Assert.notNull(status, "HttpStatusCode must not be null"); this.status = status; } @@ -142,12 +142,12 @@ public class ResponseEntity extends HttpEntity { * Return the HTTP status code of the response. * @return the HTTP status as an HttpStatus enum entry */ - public HttpStatus getStatusCode() { - if (this.status instanceof HttpStatus) { - return (HttpStatus) this.status; + public HttpStatusCode getStatusCode() { + if (this.status instanceof HttpStatusCode statusCode) { + return statusCode; } else { - return HttpStatus.valueOf((Integer) this.status); + return HttpStatusCode.valueOf((Integer) this.status); } } @@ -155,10 +155,12 @@ public class ResponseEntity extends HttpEntity { * Return the HTTP status code of the response. * @return the HTTP status as an int value * @since 4.3 + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} */ + @Deprecated public int getStatusCodeValue() { - if (this.status instanceof HttpStatus) { - return ((HttpStatus) this.status).value(); + if (this.status instanceof HttpStatusCode statusCode) { + return statusCode.value(); } else { return (Integer) this.status; @@ -187,9 +189,9 @@ public class ResponseEntity extends HttpEntity { public String toString() { StringBuilder builder = new StringBuilder("<"); builder.append(this.status); - if (this.status instanceof HttpStatus) { + if (this.status instanceof HttpStatus httpStatus) { builder.append(' '); - builder.append(((HttpStatus) this.status).getReasonPhrase()); + builder.append(httpStatus.getReasonPhrase()); } builder.append(','); T body = getBody(); @@ -212,8 +214,8 @@ public class ResponseEntity extends HttpEntity { * @return the created builder * @since 4.1 */ - public static BodyBuilder status(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); + public static BodyBuilder status(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); return new DefaultBuilder(status); } diff --git a/spring-web/src/main/java/org/springframework/http/client/AbstractClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/AbstractClientHttpResponse.java index f45c55c23b..d61ae965c1 100644 --- a/spring-web/src/main/java/org/springframework/http/client/AbstractClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/AbstractClientHttpResponse.java @@ -18,19 +18,21 @@ package org.springframework.http.client; import java.io.IOException; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; /** * Abstract base for {@link ClientHttpResponse}. * * @author Arjen Poutsma * @since 3.1.1 + * @deprecated with no direct replacement */ +@Deprecated public abstract class AbstractClientHttpResponse implements ClientHttpResponse { @Override - public HttpStatus getStatusCode() throws IOException { - return HttpStatus.valueOf(getRawStatusCode()); + public HttpStatusCode getStatusCode() throws IOException { + return HttpStatusCode.valueOf(getRawStatusCode()); } } diff --git a/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java b/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java index b409a9518c..5c23f6b980 100644 --- a/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java +++ b/spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java @@ -21,7 +21,7 @@ import java.io.IOException; import java.io.InputStream; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.StreamUtils; @@ -46,11 +46,12 @@ final class BufferingClientHttpResponseWrapper implements ClientHttpResponse { @Override - public HttpStatus getStatusCode() throws IOException { + public HttpStatusCode getStatusCode() throws IOException { return this.response.getStatusCode(); } @Override + @Deprecated public int getRawStatusCode() throws IOException { return this.response.getRawStatusCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/ClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/ClientHttpResponse.java index f0ecff26eb..0da42bbe90 100644 --- a/spring-web/src/main/java/org/springframework/http/client/ClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/ClientHttpResponse.java @@ -20,7 +20,7 @@ import java.io.Closeable; import java.io.IOException; import org.springframework.http.HttpInputMessage; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; /** * Represents a client-side HTTP response. @@ -36,26 +36,21 @@ import org.springframework.http.HttpStatus; public interface ClientHttpResponse extends HttpInputMessage, Closeable { /** - * Get the HTTP status code as an {@link HttpStatus} enum value. - *

For status codes not supported by {@code HttpStatus}, use - * {@link #getRawStatusCode()} instead. - * @return the HTTP status as an HttpStatus enum value (never {@code null}) + * Get the HTTP status code as an {@link HttpStatusCode}. + * @return the HTTP status as {@code HttpStatusCode} value (never {@code null}) * @throws IOException in case of I/O errors - * @throws IllegalArgumentException in case of an unknown HTTP status code - * @since #getRawStatusCode() - * @see HttpStatus#valueOf(int) */ - HttpStatus getStatusCode() throws IOException; + HttpStatusCode getStatusCode() throws IOException; /** - * Get the HTTP status code (potentially non-standard and not - * resolvable through the {@link HttpStatus} enum) as an integer. + * Get the HTTP status code as an integer. * @return the HTTP status as an integer value * @throws IOException in case of I/O errors * @since 3.1.1 * @see #getStatusCode() - * @see HttpStatus#resolve(int) + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} */ + @Deprecated int getRawStatusCode() throws IOException; /** diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java index 7d48ace787..ceec263ff2 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpResponse.java @@ -26,6 +26,7 @@ import org.apache.http.HttpResponse; import org.apache.http.util.EntityUtils; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.StreamUtils; @@ -40,7 +41,7 @@ import org.springframework.util.StreamUtils; * @since 3.1 * @see HttpComponentsClientHttpRequest#execute() */ -final class HttpComponentsClientHttpResponse extends AbstractClientHttpResponse { +final class HttpComponentsClientHttpResponse implements ClientHttpResponse { private final HttpResponse httpResponse; @@ -54,6 +55,12 @@ final class HttpComponentsClientHttpResponse extends AbstractClientHttpResponse @Override + public HttpStatusCode getStatusCode() throws IOException { + return HttpStatusCode.valueOf(this.httpResponse.getStatusLine().getStatusCode()); + } + + @Override + @Deprecated public int getRawStatusCode() throws IOException { return this.httpResponse.getStatusLine().getStatusCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpResponse.java index c266454225..d92bc90980 100644 --- a/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpResponse.java @@ -23,6 +23,7 @@ import okhttp3.Response; import okhttp3.ResponseBody; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StreamUtils; @@ -35,7 +36,7 @@ import org.springframework.util.StreamUtils; * @author Roy Clarkson * @since 4.3 */ -class OkHttp3ClientHttpResponse extends AbstractClientHttpResponse { +class OkHttp3ClientHttpResponse implements ClientHttpResponse { private final Response response; @@ -50,6 +51,12 @@ class OkHttp3ClientHttpResponse extends AbstractClientHttpResponse { @Override + public HttpStatusCode getStatusCode() throws IOException { + return HttpStatusCode.valueOf(this.response.code()); + } + + @Override + @Deprecated public int getRawStatusCode() { return this.response.code(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpResponse.java index fef8f723ea..be507db47a 100644 --- a/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpResponse.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; @@ -34,7 +35,7 @@ import org.springframework.util.StringUtils; * @author Brian Clozel * @since 3.0 */ -final class SimpleClientHttpResponse extends AbstractClientHttpResponse { +final class SimpleClientHttpResponse implements ClientHttpResponse { private final HttpURLConnection connection; @@ -51,6 +52,12 @@ final class SimpleClientHttpResponse extends AbstractClientHttpResponse { @Override + public HttpStatusCode getStatusCode() throws IOException { + return HttpStatusCode.valueOf(this.connection.getResponseCode()); + } + + @Override + @Deprecated public int getRawStatusCode() throws IOException { return this.connection.getResponseCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponse.java index ee2b8c3609..18acaf00d9 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponse.java @@ -16,7 +16,7 @@ package org.springframework.http.client.reactive; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ReactiveHttpInputMessage; import org.springframework.http.ResponseCookie; import org.springframework.util.MultiValueMap; @@ -41,22 +41,19 @@ public interface ClientHttpResponse extends ReactiveHttpInputMessage { } /** - * Return the HTTP status code as an {@link HttpStatus} enum value. - * @return the HTTP status as an HttpStatus enum value (never {@code null}) - * @throws IllegalArgumentException in case of an unknown HTTP status code - * @since #getRawStatusCode() - * @see HttpStatus#valueOf(int) + * Return the HTTP status code as an {@link HttpStatusCode}. + * @return the HTTP status as {@code HttpStatusCode} value (never {@code null}) */ - HttpStatus getStatusCode(); + HttpStatusCode getStatusCode(); /** - * Return the HTTP status code (potentially non-standard and not - * resolvable through the {@link HttpStatus} enum) as an integer. + * Return the HTTP status code as an integer. * @return the HTTP status as an integer value * @since 5.0.6 * @see #getStatusCode() - * @see HttpStatus#resolve(int) + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} */ + @Deprecated int getRawStatusCode(); /** diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java index 389a42b338..279c9351b1 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java @@ -20,7 +20,7 @@ import reactor.core.publisher.Flux; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.util.Assert; import org.springframework.util.MultiValueMap; @@ -56,11 +56,12 @@ public class ClientHttpResponseDecorator implements ClientHttpResponse { } @Override - public HttpStatus getStatusCode() { + public HttpStatusCode getStatusCode() { return this.delegate.getStatusCode(); } @Override + @Deprecated public int getRawStatusCode() { return this.delegate.getRawStatusCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpResponse.java index c284834e15..07597a54a7 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpResponse.java @@ -29,7 +29,7 @@ import reactor.core.publisher.Flux; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -68,11 +68,12 @@ class HttpComponentsClientHttpResponse implements ClientHttpResponse { @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.message.getHead().getCode()); + public HttpStatusCode getStatusCode() { + return HttpStatusCode.valueOf(this.message.getHead().getCode()); } @Override + @Deprecated public int getRawStatusCode() { return this.message.getHead().getCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/JdkClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/reactive/JdkClientHttpResponse.java index 8beacd5809..5e0820577c 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/JdkClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/JdkClientHttpResponse.java @@ -35,7 +35,7 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; @@ -80,11 +80,12 @@ class JdkClientHttpResponse implements ClientHttpResponse { @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.response.statusCode()); + public HttpStatusCode getStatusCode() { + return HttpStatusCode.valueOf(this.response.statusCode()); } @Override + @Deprecated public int getRawStatusCode() { return this.response.statusCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpResponse.java index 22cde72ac2..7cd6dc41d1 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpResponse.java @@ -27,7 +27,7 @@ import reactor.core.publisher.Flux; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; @@ -64,11 +64,12 @@ class JettyClientHttpResponse implements ClientHttpResponse { @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(getRawStatusCode()); + public HttpStatusCode getStatusCode() { + return HttpStatusCode.valueOf(this.reactiveResponse.getStatus()); } @Override + @Deprecated public int getRawStatusCode() { return this.reactiveResponse.getStatus(); } diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpResponse.java index 5139d9e3ae..ff8354bca0 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpResponse.java @@ -34,7 +34,7 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; @@ -135,11 +135,12 @@ class ReactorClientHttpResponse implements ClientHttpResponse { } @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(getRawStatusCode()); + public HttpStatusCode getStatusCode() { + return HttpStatusCode.valueOf(this.response.status().code()); } @Override + @Deprecated public int getRawStatusCode() { return this.response.status().code(); } diff --git a/spring-web/src/main/java/org/springframework/http/server/DelegatingServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/DelegatingServerHttpResponse.java index 43dc6e57b5..ae94ffbe49 100644 --- a/spring-web/src/main/java/org/springframework/http/server/DelegatingServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/DelegatingServerHttpResponse.java @@ -20,7 +20,7 @@ import java.io.IOException; import java.io.OutputStream; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.util.Assert; /** @@ -52,7 +52,7 @@ public class DelegatingServerHttpResponse implements ServerHttpResponse { } @Override - public void setStatusCode(HttpStatus status) { + public void setStatusCode(HttpStatusCode status) { this.delegate.setStatusCode(status); } diff --git a/spring-web/src/main/java/org/springframework/http/server/ServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/ServerHttpResponse.java index e47d93c313..da9de16e45 100644 --- a/spring-web/src/main/java/org/springframework/http/server/ServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/ServerHttpResponse.java @@ -21,7 +21,7 @@ import java.io.Flushable; import java.io.IOException; import org.springframework.http.HttpOutputMessage; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; /** * Represents a server-side HTTP response. @@ -35,7 +35,7 @@ public interface ServerHttpResponse extends HttpOutputMessage, Flushable, Closea * Set the HTTP status code of the response. * @param status the HTTP status as an HttpStatus enum value */ - void setStatusCode(HttpStatus status); + void setStatusCode(HttpStatusCode status); /** * Ensure that the headers and the content of the response are written out. diff --git a/spring-web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java index 1822b10f2b..15ae654093 100644 --- a/spring-web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java @@ -26,7 +26,7 @@ import java.util.List; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -71,7 +71,7 @@ public class ServletServerHttpResponse implements ServerHttpResponse { } @Override - public void setStatusCode(HttpStatus status) { + public void setStatusCode(HttpStatusCode status) { Assert.notNull(status, "HttpStatus must not be null"); this.servletResponse.setStatus(status.value()); } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpResponse.java index 3e6120e67a..d40e786823 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpResponse.java @@ -31,7 +31,7 @@ import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.PooledDataBuffer; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -62,7 +62,7 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse { private final DataBufferFactory dataBufferFactory; @Nullable - private Integer statusCode; + private HttpStatusCode statusCode; private final HttpHeaders headers; @@ -95,37 +95,32 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse { } @Override - public boolean setStatusCode(@Nullable HttpStatus status) { + public boolean setStatusCode(@Nullable HttpStatusCode status) { if (this.state.get() == State.COMMITTED) { return false; } else { - this.statusCode = (status != null ? status.value() : null); + this.statusCode = status; return true; } } @Override @Nullable - public HttpStatus getStatusCode() { - return (this.statusCode != null ? HttpStatus.resolve(this.statusCode) : null); + public HttpStatusCode getStatusCode() { + return this.statusCode; } @Override public boolean setRawStatusCode(@Nullable Integer statusCode) { - if (this.state.get() == State.COMMITTED) { - return false; - } - else { - this.statusCode = statusCode; - return true; - } + return setStatusCode(statusCode != null ? HttpStatusCode.valueOf(statusCode) : null); } @Override @Nullable + @Deprecated public Integer getRawStatusCode() { - return this.statusCode; + return this.statusCode != null ? this.statusCode.value() : null; } @Override diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpResponse.java index de8fd4121c..19fcb6715b 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpResponse.java @@ -34,7 +34,7 @@ import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.http.ZeroCopyHttpOutputMessage; import org.springframework.util.Assert; @@ -68,12 +68,13 @@ class ReactorServerHttpResponse extends AbstractServerHttpResponse implements Ze } @Override - public HttpStatus getStatusCode() { - HttpStatus status = super.getStatusCode(); - return (status != null ? status : HttpStatus.resolve(this.response.status().code())); + public HttpStatusCode getStatusCode() { + HttpStatusCode status = super.getStatusCode(); + return (status != null ? status : HttpStatusCode.valueOf(this.response.status().code())); } @Override + @Deprecated public Integer getRawStatusCode() { Integer status = super.getRawStatusCode(); return (status != null ? status : this.response.status().code()); @@ -81,9 +82,9 @@ class ReactorServerHttpResponse extends AbstractServerHttpResponse implements Ze @Override protected void applyStatusCode() { - Integer status = super.getRawStatusCode(); + HttpStatusCode status = super.getStatusCode(); if (status != null) { - this.response.status(status); + this.response.status(status.value()); } } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponse.java index eb665e362e..2879e1e486 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponse.java @@ -16,7 +16,7 @@ package org.springframework.http.server.reactive; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ReactiveHttpOutputMessage; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; @@ -34,42 +34,30 @@ public interface ServerHttpResponse extends ReactiveHttpOutputMessage { /** * Set the HTTP status code of the response. - * @param status the HTTP status as an {@link HttpStatus} enum value + * @param status the HTTP status as an {@link HttpStatusCode} value * @return {@code false} if the status code change wasn't processed because * the HTTP response is committed, {@code true} if successfully set. */ - boolean setStatusCode(@Nullable HttpStatus status); + boolean setStatusCode(@Nullable HttpStatusCode status); /** * Return the status code that has been set, or otherwise fall back on the * status of the response from the underlying server. The return value may - * be {@code null} if the status code value is outside the - * {@link HttpStatus} enum range, or if there is no default value from the + * be {@code null} if there is no default value from the * underlying server. */ @Nullable - HttpStatus getStatusCode(); + HttpStatusCode getStatusCode(); /** - * Set the HTTP status code to the given value (potentially non-standard and - * not resolvable through the {@link HttpStatus} enum) as an integer. + * Set the HTTP status code to the given value as an integer. * @param value the status code value * @return {@code false} if the status code change wasn't processed because * the HTTP response is committed, {@code true} if successfully set. * @since 5.2.4 */ default boolean setRawStatusCode(@Nullable Integer value) { - if (value == null) { - return setStatusCode(null); - } - else { - HttpStatus httpStatus = HttpStatus.resolve(value); - if (httpStatus == null) { - throw new IllegalStateException( - "Unresolvable HttpStatus for general ServerHttpResponse: " + value); - } - return setStatusCode(httpStatus); - } + return setStatusCode(value != null ? HttpStatusCode.valueOf(value) : null); } /** @@ -77,10 +65,12 @@ public interface ServerHttpResponse extends ReactiveHttpOutputMessage { * status of the response from the underlying server. The return value may * be {@code null} if there is no default value from the underlying server. * @since 5.2.4 + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} */ @Nullable + @Deprecated default Integer getRawStatusCode() { - HttpStatus httpStatus = getStatusCode(); + HttpStatusCode httpStatus = getStatusCode(); return (httpStatus != null ? httpStatus.value() : null); } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java index c6574c26f3..de285b6065 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpResponseDecorator.java @@ -24,7 +24,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -56,12 +56,12 @@ public class ServerHttpResponseDecorator implements ServerHttpResponse { // ServerHttpResponse delegation methods... @Override - public boolean setStatusCode(@Nullable HttpStatus status) { + public boolean setStatusCode(@Nullable HttpStatusCode status) { return getDelegate().setStatusCode(status); } @Override - public HttpStatus getStatusCode() { + public HttpStatusCode getStatusCode() { return getDelegate().getStatusCode(); } @@ -71,6 +71,7 @@ public class ServerHttpResponseDecorator implements ServerHttpResponse { } @Override + @Deprecated public Integer getRawStatusCode() { return getDelegate().getRawStatusCode(); } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java index 949be403dd..464cb35e5c 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java @@ -34,7 +34,7 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; @@ -101,12 +101,13 @@ class ServletServerHttpResponse extends AbstractListenerServerHttpResponse { } @Override - public HttpStatus getStatusCode() { - HttpStatus status = super.getStatusCode(); - return (status != null ? status : HttpStatus.resolve(this.response.getStatus())); + public HttpStatusCode getStatusCode() { + HttpStatusCode status = super.getStatusCode(); + return (status != null ? status : HttpStatusCode.valueOf(this.response.getStatus())); } @Override + @Deprecated public Integer getRawStatusCode() { Integer status = super.getRawStatusCode(); return (status != null ? status : this.response.getStatus()); @@ -114,9 +115,9 @@ class ServletServerHttpResponse extends AbstractListenerServerHttpResponse { @Override protected void applyStatusCode() { - Integer status = super.getRawStatusCode(); + HttpStatusCode status = super.getStatusCode(); if (status != null) { - this.response.setStatus(status); + this.response.setStatus(status.value()); } } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java index 5f8034b724..637a04d1f0 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java @@ -35,7 +35,7 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.http.ZeroCopyHttpOutputMessage; import org.springframework.lang.Nullable; @@ -81,12 +81,13 @@ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse impl } @Override - public HttpStatus getStatusCode() { - HttpStatus status = super.getStatusCode(); - return (status != null ? status : HttpStatus.resolve(this.exchange.getStatusCode())); + public HttpStatusCode getStatusCode() { + HttpStatusCode status = super.getStatusCode(); + return (status != null ? status : HttpStatusCode.valueOf(this.exchange.getStatusCode())); } @Override + @Deprecated public Integer getRawStatusCode() { Integer status = super.getRawStatusCode(); return (status != null ? status : this.exchange.getStatusCode()); @@ -94,9 +95,9 @@ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse impl @Override protected void applyStatusCode() { - Integer status = super.getRawStatusCode(); + HttpStatusCode status = super.getStatusCode(); if (status != null) { - this.exchange.setStatusCode(status); + this.exchange.setStatusCode(status.value()); } } diff --git a/spring-web/src/main/java/org/springframework/web/ErrorResponse.java b/spring-web/src/main/java/org/springframework/web/ErrorResponse.java index a8527a1852..11d8375a11 100644 --- a/spring-web/src/main/java/org/springframework/web/ErrorResponse.java +++ b/spring-web/src/main/java/org/springframework/web/ErrorResponse.java @@ -17,7 +17,7 @@ package org.springframework.web; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; @@ -41,18 +41,9 @@ import org.springframework.http.ProblemDetail; public interface ErrorResponse { /** - * Return the HTTP status to use for the response. - * @throws IllegalArgumentException for an unknown HTTP status code + * Return the HTTP status code to use for the response. */ - default HttpStatus getStatus() { - return HttpStatus.valueOf(getRawStatusCode()); - } - - /** - * Return the HTTP status value for the response, potentially non-standard - * and not resolvable via {@link HttpStatus}. - */ - int getRawStatusCode(); + HttpStatusCode getStatusCode(); /** * Return headers to use for the response. diff --git a/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java b/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java index 04dbfd8e45..ebd978709b 100644 --- a/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java +++ b/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java @@ -16,13 +16,12 @@ package org.springframework.web; - import java.net.URI; import org.springframework.core.NestedExceptionUtils; import org.springframework.core.NestedRuntimeException; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.lang.Nullable; @@ -43,7 +42,7 @@ import org.springframework.lang.Nullable; @SuppressWarnings("serial") public class ErrorResponseException extends NestedRuntimeException implements ErrorResponse { - private final int status; + private final HttpStatusCode status; private final HttpHeaders headers = new HttpHeaders(); @@ -51,40 +50,31 @@ public class ErrorResponseException extends NestedRuntimeException implements Er /** - * Constructor with a well-known {@link HttpStatus}. + * Constructor with a {@link HttpStatusCode}. */ - public ErrorResponseException(HttpStatus status) { + public ErrorResponseException(HttpStatusCode status) { this(status, null); } /** - * Constructor with a well-known {@link HttpStatus} and an optional cause. + * Constructor with a {@link HttpStatusCode} and an optional cause. */ - public ErrorResponseException(HttpStatus status, @Nullable Throwable cause) { - this(status.value(), cause); - } - - /** - * Constructor that accepts any status value, possibly not resolvable as an - * {@link HttpStatus} enum, and an optional cause. - */ - public ErrorResponseException(int status, @Nullable Throwable cause) { - this(status, ProblemDetail.forRawStatusCode(status), cause); + public ErrorResponseException(HttpStatusCode status, @Nullable Throwable cause) { + this(status, ProblemDetail.forStatus(status), cause); } /** * Constructor with a given {@link ProblemDetail} instance, possibly a * subclass of {@code ProblemDetail} with extended fields. */ - public ErrorResponseException(int status, ProblemDetail body, @Nullable Throwable cause) { + public ErrorResponseException(HttpStatusCode status, ProblemDetail body, @Nullable Throwable cause) { super(null, cause); this.status = status; this.body = body; } - @Override - public int getRawStatusCode() { + public HttpStatusCode getStatusCode() { return this.status; } @@ -147,9 +137,7 @@ public class ErrorResponseException extends NestedRuntimeException implements Er @Override public String getMessage() { - HttpStatus httpStatus = HttpStatus.resolve(this.status); - String message = (httpStatus != null ? httpStatus : String.valueOf(this.status)) + - (!this.headers.isEmpty() ? ", headers=" + this.headers : "") + ", " + this.body; + String message = this.status + (!this.headers.isEmpty() ? ", headers=" + this.headers : "") + ", " + this.body; return NestedExceptionUtils.buildMessage(message, getCause()); } diff --git a/spring-web/src/main/java/org/springframework/web/HttpMediaTypeException.java b/spring-web/src/main/java/org/springframework/web/HttpMediaTypeException.java index a5c807213c..17230b4777 100644 --- a/spring-web/src/main/java/org/springframework/web/HttpMediaTypeException.java +++ b/spring-web/src/main/java/org/springframework/web/HttpMediaTypeException.java @@ -35,7 +35,7 @@ public abstract class HttpMediaTypeException extends ServletException implements private final List supportedMediaTypes; - private final ProblemDetail body = ProblemDetail.forRawStatusCode(getRawStatusCode()); + private final ProblemDetail body = ProblemDetail.forStatus(getStatusCode()); /** diff --git a/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotAcceptableException.java b/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotAcceptableException.java index d405efa392..417b3cc92d 100644 --- a/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotAcceptableException.java +++ b/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotAcceptableException.java @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.util.CollectionUtils; @@ -55,8 +56,8 @@ public class HttpMediaTypeNotAcceptableException extends HttpMediaTypeException @Override - public int getRawStatusCode() { - return HttpStatus.NOT_ACCEPTABLE.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.NOT_ACCEPTABLE; } @Override diff --git a/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotSupportedException.java b/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotSupportedException.java index 7a55ce2a8e..1a08ef005f 100644 --- a/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotSupportedException.java +++ b/spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotSupportedException.java @@ -21,6 +21,7 @@ import java.util.List; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; @@ -104,8 +105,8 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException { } @Override - public int getRawStatusCode() { - return HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.UNSUPPORTED_MEDIA_TYPE; } @Override diff --git a/spring-web/src/main/java/org/springframework/web/HttpRequestMethodNotSupportedException.java b/spring-web/src/main/java/org/springframework/web/HttpRequestMethodNotSupportedException.java index 1f86b399b8..f9abbf683f 100644 --- a/spring-web/src/main/java/org/springframework/web/HttpRequestMethodNotSupportedException.java +++ b/spring-web/src/main/java/org/springframework/web/HttpRequestMethodNotSupportedException.java @@ -25,6 +25,7 @@ import jakarta.servlet.ServletException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; @@ -95,7 +96,7 @@ public class HttpRequestMethodNotSupportedException extends ServletException imp this.supportedMethods = supportedMethods; String detail = "Method '" + method + "' is not supported."; - this.body = ProblemDetail.forRawStatusCode(getRawStatusCode()).withDetail(detail); + this.body = ProblemDetail.forStatus(getStatusCode()).withDetail(detail); } @@ -133,8 +134,8 @@ public class HttpRequestMethodNotSupportedException extends ServletException imp } @Override - public int getRawStatusCode() { - return HttpStatus.METHOD_NOT_ALLOWED.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.METHOD_NOT_ALLOWED; } @Override diff --git a/spring-web/src/main/java/org/springframework/web/bind/MethodArgumentNotValidException.java b/spring-web/src/main/java/org/springframework/web/bind/MethodArgumentNotValidException.java index 876e1c235e..00e5db684f 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/MethodArgumentNotValidException.java +++ b/spring-web/src/main/java/org/springframework/web/bind/MethodArgumentNotValidException.java @@ -18,6 +18,7 @@ package org.springframework.web.bind; import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; @@ -48,13 +49,12 @@ public class MethodArgumentNotValidException extends BindException implements Er public MethodArgumentNotValidException(MethodParameter parameter, BindingResult bindingResult) { super(bindingResult); this.parameter = parameter; - this.body = ProblemDetail.forRawStatusCode(getRawStatusCode()).withDetail("Invalid request content."); + this.body = ProblemDetail.forStatus(getStatusCode()).withDetail("Invalid request content."); } - @Override - public int getRawStatusCode() { - return HttpStatus.BAD_REQUEST.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.BAD_REQUEST; } @Override diff --git a/spring-web/src/main/java/org/springframework/web/bind/MissingPathVariableException.java b/spring-web/src/main/java/org/springframework/web/bind/MissingPathVariableException.java index f7f3eba5d0..5cc6ceb423 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/MissingPathVariableException.java +++ b/spring-web/src/main/java/org/springframework/web/bind/MissingPathVariableException.java @@ -18,6 +18,7 @@ package org.springframework.web.bind; import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; /** * {@link ServletRequestBindingException} subclass that indicates that a path @@ -85,10 +86,9 @@ public class MissingPathVariableException extends MissingRequestValueException { return this.parameter; } - @Override - public int getRawStatusCode() { - return HttpStatus.INTERNAL_SERVER_ERROR.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.INTERNAL_SERVER_ERROR; } } diff --git a/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java b/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java index a3bcc4a836..2767f763bf 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java +++ b/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java @@ -17,6 +17,7 @@ package org.springframework.web.bind; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.web.ErrorResponse; import org.springframework.web.util.NestedServletException; @@ -35,7 +36,7 @@ import org.springframework.web.util.NestedServletException; @SuppressWarnings("serial") public class ServletRequestBindingException extends NestedServletException implements ErrorResponse { - private final ProblemDetail body = ProblemDetail.forRawStatusCode(getRawStatusCode()); + private final ProblemDetail body = ProblemDetail.forStatus(getStatusCode()); /** @@ -55,10 +56,9 @@ public class ServletRequestBindingException extends NestedServletException imple super(msg, cause); } - @Override - public int getRawStatusCode() { - return HttpStatus.BAD_REQUEST.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.BAD_REQUEST; } @Override diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java index 55165060d0..d7e9d87359 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java @@ -23,6 +23,7 @@ import java.nio.charset.StandardCharsets; import org.springframework.core.log.LogFormatUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.lang.Nullable; @@ -35,7 +36,7 @@ import org.springframework.util.ObjectUtils; *

This error handler checks for the status code on the * {@link ClientHttpResponse}. Any code in the 4xx or 5xx series is considered * to be an error. This behavior can be changed by overriding - * {@link #hasError(HttpStatus)}. Unknown status codes will be ignored by + * {@link #hasError(HttpStatusCode)}. Unknown status codes will be ignored by * {@link #hasError(ClientHttpResponse)}. * *

See {@link #handleError(ClientHttpResponse)} for more details on specific @@ -50,28 +51,25 @@ import org.springframework.util.ObjectUtils; public class DefaultResponseErrorHandler implements ResponseErrorHandler { /** - * Delegates to {@link #hasError(HttpStatus)} (for a standard status enum value) or - * {@link #hasError(int)} (for an unknown status code) with the response status code. - * @see ClientHttpResponse#getRawStatusCode() - * @see #hasError(HttpStatus) - * @see #hasError(int) + * Delegates to {@link #hasError(HttpStatusCode)} with the response status code. + * @see ClientHttpResponse#getStatusCode() + * @see #hasError(HttpStatusCode) */ @Override public boolean hasError(ClientHttpResponse response) throws IOException { - int rawStatusCode = response.getRawStatusCode(); - HttpStatus statusCode = HttpStatus.resolve(rawStatusCode); - return (statusCode != null ? hasError(statusCode) : hasError(rawStatusCode)); + HttpStatusCode statusCode = response.getStatusCode(); + return hasError(statusCode); } /** * Template method called from {@link #hasError(ClientHttpResponse)}. - *

The default implementation checks {@link HttpStatus#isError()}. + *

The default implementation checks {@link HttpStatusCode#isError()}. * Can be overridden in subclasses. - * @param statusCode the HTTP status code as enum value + * @param statusCode the HTTP status code * @return {@code true} if the response indicates an error; {@code false} otherwise - * @see HttpStatus#isError() + * @see HttpStatusCode#isError() */ - protected boolean hasError(HttpStatus statusCode) { + protected boolean hasError(HttpStatusCode statusCode) { return statusCode.isError(); } @@ -81,14 +79,16 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { * {@link org.springframework.http.HttpStatus.Series#CLIENT_ERROR CLIENT_ERROR} or * {@link org.springframework.http.HttpStatus.Series#SERVER_ERROR SERVER_ERROR}. * Can be overridden in subclasses. - * @param unknownStatusCode the HTTP status code as raw value + * @param statusCode the HTTP status code as raw value * @return {@code true} if the response indicates an error; {@code false} otherwise * @since 4.3.21 * @see org.springframework.http.HttpStatus.Series#CLIENT_ERROR * @see org.springframework.http.HttpStatus.Series#SERVER_ERROR + * @deprecated in favor of {@link #hasError(HttpStatusCode)} */ - protected boolean hasError(int unknownStatusCode) { - HttpStatus.Series series = HttpStatus.Series.resolve(unknownStatusCode); + @Deprecated + protected boolean hasError(int statusCode) { + HttpStatus.Series series = HttpStatus.Series.resolve(statusCode); return (series == HttpStatus.Series.CLIENT_ERROR || series == HttpStatus.Series.SERVER_ERROR); } @@ -106,19 +106,11 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { * {@link HttpStatus} enum range. * * @throws UnknownHttpStatusCodeException in case of an unresolvable status code - * @see #handleError(ClientHttpResponse, HttpStatus) + * @see #handleError(ClientHttpResponse, HttpStatusCode) */ @Override public void handleError(ClientHttpResponse response) throws IOException { - HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode()); - if (statusCode == null) { - byte[] body = getResponseBody(response); - String message = getErrorMessage(response.getRawStatusCode(), - response.getStatusText(), body, getCharset(response)); - throw new UnknownHttpStatusCodeException(message, - response.getRawStatusCode(), response.getStatusText(), - response.getHeaders(), body, getCharset(response)); - } + HttpStatusCode statusCode = response.getStatusCode(); handleError(response, statusCode); } @@ -156,20 +148,21 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { * @see HttpClientErrorException#create * @see HttpServerErrorException#create */ - protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException { + protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode) throws IOException { String statusText = response.getStatusText(); 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(message, statusCode, statusText, headers, body, charset); - case SERVER_ERROR -> - throw HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset); - default -> - throw new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset); + if (statusCode.is4xxClientError()) { + throw HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset); + } + else if (statusCode.is5xxServerError()) { + throw HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset); + } + else { + throw new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset); } } diff --git a/spring-web/src/main/java/org/springframework/web/client/ExtractingResponseErrorHandler.java b/spring-web/src/main/java/org/springframework/web/client/ExtractingResponseErrorHandler.java index bceee0da2e..72cd840a30 100644 --- a/spring-web/src/main/java/org/springframework/web/client/ExtractingResponseErrorHandler.java +++ b/spring-web/src/main/java/org/springframework/web/client/ExtractingResponseErrorHandler.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.lang.Nullable; @@ -59,7 +60,7 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler private List> messageConverters = Collections.emptyList(); - private final Map> statusMapping = new LinkedHashMap<>(); + private final Map> statusMapping = new LinkedHashMap<>(); private final Map> seriesMapping = new LinkedHashMap<>(); @@ -97,7 +98,7 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler * {@linkplain #setMessageConverters(List) configured message converters} to convert the * response into the mapped subclass of {@link RestClientException}. */ - public void setStatusMapping(Map> statusMapping) { + public void setStatusMapping(Map> statusMapping) { if (!CollectionUtils.isEmpty(statusMapping)) { this.statusMapping.putAll(statusMapping); } @@ -120,12 +121,13 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler @Override - protected boolean hasError(HttpStatus statusCode) { + protected boolean hasError(HttpStatusCode statusCode) { if (this.statusMapping.containsKey(statusCode)) { return this.statusMapping.get(statusCode) != null; } - else if (this.seriesMapping.containsKey(statusCode.series())) { - return this.seriesMapping.get(statusCode.series()) != null; + HttpStatus.Series series = HttpStatus.Series.resolve(statusCode.value()); + if (this.seriesMapping.containsKey(series)) { + return this.seriesMapping.get(series) != null; } else { return super.hasError(statusCode); @@ -133,12 +135,13 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler } @Override - public void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException { + public void handleError(ClientHttpResponse response, HttpStatusCode statusCode) throws IOException { if (this.statusMapping.containsKey(statusCode)) { extract(this.statusMapping.get(statusCode), response); } - else if (this.seriesMapping.containsKey(statusCode.series())) { - extract(this.seriesMapping.get(statusCode.series()), response); + HttpStatus.Series series = HttpStatus.Series.resolve(statusCode.value()); + if (this.seriesMapping.containsKey(series)) { + extract(this.seriesMapping.get(series), response); } else { super.handleError(response, statusCode); diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java b/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java index ff6e3f8308..6ec0ad02d2 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpClientErrorException.java @@ -20,6 +20,7 @@ import java.nio.charset.Charset; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; /** @@ -37,14 +38,14 @@ public class HttpClientErrorException extends HttpStatusCodeException { /** * Constructor with a status code only. */ - public HttpClientErrorException(HttpStatus statusCode) { + public HttpClientErrorException(HttpStatusCode statusCode) { super(statusCode); } /** * Constructor with a status code and status text. */ - public HttpClientErrorException(HttpStatus statusCode, String statusText) { + public HttpClientErrorException(HttpStatusCode statusCode, String statusText) { super(statusCode, statusText); } @@ -52,7 +53,7 @@ public class HttpClientErrorException extends HttpStatusCodeException { * Constructor with a status code and status text, and content. */ public HttpClientErrorException( - HttpStatus statusCode, String statusText, @Nullable byte[] body, @Nullable Charset responseCharset) { + HttpStatusCode statusCode, String statusText, @Nullable byte[] body, @Nullable Charset responseCharset) { super(statusCode, statusText, body, responseCharset); } @@ -60,7 +61,7 @@ public class HttpClientErrorException extends HttpStatusCodeException { /** * Constructor with a status code and status text, headers, and content. */ - public HttpClientErrorException(HttpStatus statusCode, String statusText, + public HttpClientErrorException(HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset responseCharset) { super(statusCode, statusText, headers, body, responseCharset); @@ -71,7 +72,7 @@ public class HttpClientErrorException extends HttpStatusCodeException { * and an prepared message. * @since 5.2.2 */ - public HttpClientErrorException(String message, HttpStatus statusCode, String statusText, + public HttpClientErrorException(String message, HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset responseCharset) { super(message, statusCode, statusText, headers, body, responseCharset); @@ -83,68 +84,64 @@ public class HttpClientErrorException extends HttpStatusCodeException { * @since 5.1 */ public static HttpClientErrorException create( - HttpStatus statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { + HttpStatusCode 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)} + * Variant of {@link #create(HttpStatusCode, String, HttpHeaders, byte[], Charset)} * with an optional prepared message. * @since 5.2.2 */ - public static HttpClientErrorException create(@Nullable String message, HttpStatus statusCode, + public static HttpClientErrorException create(@Nullable String message, HttpStatusCode statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { - switch (statusCode) { - case BAD_REQUEST: - return message != null ? - new HttpClientErrorException.BadRequest(message, statusText, headers, body, charset) : - new HttpClientErrorException.BadRequest(statusText, headers, body, charset); - case UNAUTHORIZED: - return message != null ? - new HttpClientErrorException.Unauthorized(message, statusText, headers, body, charset) : - new HttpClientErrorException.Unauthorized(statusText, headers, body, charset); - case FORBIDDEN: - return message != null ? - new HttpClientErrorException.Forbidden(message, statusText, headers, body, charset) : - new HttpClientErrorException.Forbidden(statusText, headers, body, charset); - case NOT_FOUND: - return message != null ? - new HttpClientErrorException.NotFound(message, statusText, headers, body, charset) : - new HttpClientErrorException.NotFound(statusText, headers, body, charset); - case METHOD_NOT_ALLOWED: - return message != null ? - new HttpClientErrorException.MethodNotAllowed(message, statusText, headers, body, charset) : - new HttpClientErrorException.MethodNotAllowed(statusText, headers, body, charset); - case NOT_ACCEPTABLE: - return message != null ? - new HttpClientErrorException.NotAcceptable(message, statusText, headers, body, charset) : - new HttpClientErrorException.NotAcceptable(statusText, headers, body, charset); - case CONFLICT: - return message != null ? - new HttpClientErrorException.Conflict(message, statusText, headers, body, charset) : - new HttpClientErrorException.Conflict(statusText, headers, body, charset); - case GONE: - return message != null ? - new HttpClientErrorException.Gone(message, statusText, headers, body, charset) : - new HttpClientErrorException.Gone(statusText, headers, body, charset); - case UNSUPPORTED_MEDIA_TYPE: - return message != null ? - new HttpClientErrorException.UnsupportedMediaType(message, statusText, headers, body, charset) : - new HttpClientErrorException.UnsupportedMediaType(statusText, headers, body, charset); - case TOO_MANY_REQUESTS: - return message != null ? - new HttpClientErrorException.TooManyRequests(message, statusText, headers, body, charset) : - new HttpClientErrorException.TooManyRequests(statusText, headers, body, charset); - case UNPROCESSABLE_ENTITY: - return message != null ? - new HttpClientErrorException.UnprocessableEntity(message, statusText, headers, body, charset) : - new HttpClientErrorException.UnprocessableEntity(statusText, headers, body, charset); - default: - return message != null ? + if (statusCode instanceof HttpStatus status) { + return switch (status) { + case BAD_REQUEST -> message != null ? + new BadRequest(message, statusText, headers, body, charset) : + new BadRequest(statusText, headers, body, charset); + case UNAUTHORIZED -> message != null ? + new Unauthorized(message, statusText, headers, body, charset) : + new Unauthorized(statusText, headers, body, charset); + case FORBIDDEN -> message != null ? + new Forbidden(message, statusText, headers, body, charset) : + new Forbidden(statusText, headers, body, charset); + case NOT_FOUND -> message != null ? + new NotFound(message, statusText, headers, body, charset) : + new NotFound(statusText, headers, body, charset); + case METHOD_NOT_ALLOWED -> message != null ? + new MethodNotAllowed(message, statusText, headers, body, charset) : + new MethodNotAllowed(statusText, headers, body, charset); + case NOT_ACCEPTABLE -> message != null ? + new NotAcceptable(message, statusText, headers, body, charset) : + new NotAcceptable(statusText, headers, body, charset); + case CONFLICT -> message != null ? + new Conflict(message, statusText, headers, body, charset) : + new Conflict(statusText, headers, body, charset); + case GONE -> message != null ? + new Gone(message, statusText, headers, body, charset) : + new Gone(statusText, headers, body, charset); + case UNSUPPORTED_MEDIA_TYPE -> message != null ? + new UnsupportedMediaType(message, statusText, headers, body, charset) : + new UnsupportedMediaType(statusText, headers, body, charset); + case TOO_MANY_REQUESTS -> message != null ? + new TooManyRequests(message, statusText, headers, body, charset) : + new TooManyRequests(statusText, headers, body, charset); + case UNPROCESSABLE_ENTITY -> message != null ? + new UnprocessableEntity(message, statusText, headers, body, charset) : + new UnprocessableEntity(statusText, headers, body, charset); + default -> message != null ? new HttpClientErrorException(message, statusCode, statusText, headers, body, charset) : new HttpClientErrorException(statusCode, statusText, headers, body, charset); + }; + } + if (message != null) { + return new HttpClientErrorException(message, statusCode, statusText, headers, body, charset); + } + else { + return new HttpClientErrorException(statusCode, statusText, headers, body, charset); } } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java b/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java index 45cc426a06..246270ac87 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java @@ -122,7 +122,7 @@ public class HttpMessageConverterExtractor implements ResponseExtractor { } throw new UnknownContentTypeException(this.responseType, contentType, - responseWrapper.getRawStatusCode(), responseWrapper.getStatusText(), + responseWrapper.getStatusCode(), responseWrapper.getStatusText(), responseWrapper.getHeaders(), getResponseBody(responseWrapper)); } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java b/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java index d45eb16da9..5f207aa407 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpServerErrorException.java @@ -20,6 +20,7 @@ import java.nio.charset.Charset; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; /** @@ -37,14 +38,14 @@ public class HttpServerErrorException extends HttpStatusCodeException { /** * Constructor with a status code only. */ - public HttpServerErrorException(HttpStatus statusCode) { + public HttpServerErrorException(HttpStatusCode statusCode) { super(statusCode); } /** * Constructor with a status code and status text. */ - public HttpServerErrorException(HttpStatus statusCode, String statusText) { + public HttpServerErrorException(HttpStatusCode statusCode, String statusText) { super(statusCode, statusText); } @@ -52,7 +53,7 @@ public class HttpServerErrorException extends HttpStatusCodeException { * Constructor with a status code and status text, and content. */ public HttpServerErrorException( - HttpStatus statusCode, String statusText, @Nullable byte[] body, @Nullable Charset charset) { + HttpStatusCode statusCode, String statusText, @Nullable byte[] body, @Nullable Charset charset) { super(statusCode, statusText, body, charset); } @@ -60,7 +61,7 @@ public class HttpServerErrorException extends HttpStatusCodeException { /** * Constructor with a status code and status text, headers, and content. */ - public HttpServerErrorException(HttpStatus statusCode, String statusText, + public HttpServerErrorException(HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset) { super(statusCode, statusText, headers, body, charset); @@ -71,7 +72,7 @@ public class HttpServerErrorException extends HttpStatusCodeException { * prepared message. * @since 5.2.2 */ - public HttpServerErrorException(String message, HttpStatus statusCode, String statusText, + public HttpServerErrorException(String message, HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset) { super(message, statusCode, statusText, headers, body, charset); @@ -81,46 +82,55 @@ public class HttpServerErrorException extends HttpStatusCodeException { * Create an {@code HttpServerErrorException} or an HTTP status specific sub-class. * @since 5.1 */ - public static HttpServerErrorException create(HttpStatus statusCode, + public static HttpServerErrorException create(HttpStatusCode 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)} + * Variant of {@link #create(String, HttpStatusCode, String, HttpHeaders, byte[], Charset)} * with an optional prepared message. * @since 5.2.2. */ - public static HttpServerErrorException create(@Nullable String message, HttpStatus statusCode, + public static HttpServerErrorException create(@Nullable String message, HttpStatusCode statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) { - switch (statusCode) { - case INTERNAL_SERVER_ERROR: - return message != null ? + if (statusCode instanceof HttpStatus status) { + switch (status) { + case INTERNAL_SERVER_ERROR: + return message != null ? new HttpServerErrorException.InternalServerError(message, statusText, headers, body, charset) : - new HttpServerErrorException.InternalServerError(statusText, headers, body, charset); - case NOT_IMPLEMENTED: - return message != null ? - new HttpServerErrorException.NotImplemented(message, statusText, headers, body, charset) : - new HttpServerErrorException.NotImplemented(statusText, headers, body, charset); - case BAD_GATEWAY: - return message != null ? - new HttpServerErrorException.BadGateway(message, statusText, headers, body, charset) : - new HttpServerErrorException.BadGateway(statusText, headers, body, charset); - case SERVICE_UNAVAILABLE: - return message != null ? + new HttpServerErrorException.InternalServerError(statusText, headers, body, charset); + case NOT_IMPLEMENTED: + return message != null ? + new HttpServerErrorException.NotImplemented(message, statusText, headers, body, charset) : + new HttpServerErrorException.NotImplemented(statusText, headers, body, charset); + case BAD_GATEWAY: + return message != null ? + new HttpServerErrorException.BadGateway(message, statusText, headers, body, charset) : + new HttpServerErrorException.BadGateway(statusText, headers, body, charset); + case SERVICE_UNAVAILABLE: + return message != null ? new HttpServerErrorException.ServiceUnavailable(message, statusText, headers, body, charset) : - new HttpServerErrorException.ServiceUnavailable(statusText, headers, body, charset); - case GATEWAY_TIMEOUT: - return message != null ? - new HttpServerErrorException.GatewayTimeout(message, statusText, headers, body, charset) : - new HttpServerErrorException.GatewayTimeout(statusText, headers, body, charset); - default: - return message != null ? - new HttpServerErrorException(message, statusCode, statusText, headers, body, charset) : - new HttpServerErrorException(statusCode, statusText, headers, body, charset); + new HttpServerErrorException.ServiceUnavailable(statusText, headers, body, charset); + case GATEWAY_TIMEOUT: + return message != null ? + new HttpServerErrorException.GatewayTimeout(message, statusText, headers, body, charset) : + new HttpServerErrorException.GatewayTimeout(statusText, headers, body, charset); + default: + return message != null ? + new HttpServerErrorException(message, statusCode, statusText, headers, body, charset) : + new HttpServerErrorException(statusCode, statusText, headers, body, charset); + } } + if (message != null) { + return new HttpServerErrorException(message, statusCode, statusText, headers, body, charset); + } + else { + return new HttpServerErrorException(statusCode, statusText, headers, body, charset); + } + } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java b/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java index b660f15be8..a5e7a624c8 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpStatusCodeException.java @@ -20,11 +20,12 @@ import java.nio.charset.Charset; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; /** - * Abstract base class for exceptions based on an {@link HttpStatus}. + * Abstract base class for exceptions based on an {@link HttpStatusCode}. * * @author Arjen Poutsma * @author Chris Beams @@ -36,42 +37,48 @@ public abstract class HttpStatusCodeException extends RestClientResponseExceptio private static final long serialVersionUID = 5696801857651587810L; - private final HttpStatus statusCode; - - /** - * Construct a new instance with an {@link HttpStatus}. + * Construct a new instance with an {@link HttpStatusCode}. * @param statusCode the status code */ - protected HttpStatusCodeException(HttpStatus statusCode) { - this(statusCode, statusCode.name(), null, null, null); + protected HttpStatusCodeException(HttpStatusCode statusCode) { + this(statusCode, name(statusCode), null, null, null); + } + + private static String name(HttpStatusCode statusCode) { + if (statusCode instanceof HttpStatus status) { + return status.name(); + } + else { + return ""; + } } /** - * Construct a new instance with an {@link HttpStatus} and status text. + * Construct a new instance with an {@link HttpStatusCode} and status text. * @param statusCode the status code * @param statusText the status text */ - protected HttpStatusCodeException(HttpStatus statusCode, String statusText) { + protected HttpStatusCodeException(HttpStatusCode statusCode, String statusText) { this(statusCode, statusText, null, null, null); } /** - * Construct instance with an {@link HttpStatus}, status text, and content. + * Construct instance with an {@link HttpStatusCode}, status text, and 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, + protected HttpStatusCodeException(HttpStatusCode statusCode, String statusText, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { this(statusCode, statusText, null, responseBody, responseCharset); } /** - * Construct instance with an {@link HttpStatus}, status text, content, and + * Construct instance with an {@link HttpStatusCode}, status text, content, and * a response charset. * @param statusCode the status code * @param statusText the status text @@ -80,7 +87,7 @@ public abstract class HttpStatusCodeException extends RestClientResponseExceptio * @param responseCharset the response body charset, may be {@code null} * @since 3.1.2 */ - protected HttpStatusCodeException(HttpStatus statusCode, String statusText, + protected HttpStatusCodeException(HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { this(getMessage(statusCode, statusText), @@ -88,7 +95,7 @@ public abstract class HttpStatusCodeException extends RestClientResponseExceptio } /** - * Construct instance with an {@link HttpStatus}, status text, content, and + * Construct instance with an {@link HttpStatusCode}, status text, content, and * a response charset. * @param message the exception message * @param statusCode the status code @@ -98,25 +105,17 @@ public abstract class HttpStatusCodeException extends RestClientResponseExceptio * @param responseCharset the response body charset, may be {@code null} * @since 5.2.2 */ - protected HttpStatusCodeException(String message, HttpStatus statusCode, String statusText, + protected HttpStatusCodeException(String message, HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { - super(message, statusCode.value(), statusText, responseHeaders, responseBody, responseCharset); - this.statusCode = statusCode; + super(message, statusCode, statusText, responseHeaders, responseBody, responseCharset); } - private static String getMessage(HttpStatus statusCode, String statusText) { - if (!StringUtils.hasLength(statusText)) { - statusText = statusCode.getReasonPhrase(); + private static String getMessage(HttpStatusCode statusCode, String statusText) { + if (!StringUtils.hasLength(statusText) && statusCode instanceof HttpStatus status) { + statusText = status.getReasonPhrase(); } return statusCode.value() + " " + statusText; } - /** - * Return the HTTP status code. - */ - public HttpStatus getStatusCode() { - return this.statusCode; - } - } diff --git a/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java b/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java index 6565adc45f..aaff142a3d 100644 --- a/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java +++ b/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java @@ -22,6 +22,7 @@ import java.io.PushbackInputStream; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.ClientHttpResponse; import org.springframework.lang.Nullable; @@ -58,9 +59,9 @@ class MessageBodyClientHttpResponseWrapper implements ClientHttpResponse { * @throws IOException in case of I/O errors */ public boolean hasMessageBody() throws IOException { - HttpStatus status = HttpStatus.resolve(getRawStatusCode()); - if (status != null && (status.is1xxInformational() || status == HttpStatus.NO_CONTENT || - status == HttpStatus.NOT_MODIFIED)) { + HttpStatusCode statusCode = getStatusCode(); + if (statusCode.is1xxInformational() || statusCode == HttpStatus.NO_CONTENT || + statusCode == HttpStatus.NOT_MODIFIED) { return false; } if (getHeaders().getContentLength() == 0) { @@ -121,11 +122,12 @@ class MessageBodyClientHttpResponseWrapper implements ClientHttpResponse { } @Override - public HttpStatus getStatusCode() throws IOException { + public HttpStatusCode getStatusCode() throws IOException { return this.response.getStatusCode(); } @Override + @Deprecated public int getRawStatusCode() throws IOException { return this.response.getRawStatusCode(); } diff --git a/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java b/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java index 2a927f3769..44ff2e2aa0 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java @@ -21,6 +21,7 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; /** @@ -36,7 +37,7 @@ public class RestClientResponseException extends RestClientException { private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - private final int rawStatusCode; + private final HttpStatusCode statusCode; private final String statusText; @@ -59,9 +60,22 @@ public class RestClientResponseException extends RestClientException { */ public RestClientResponseException(String message, int statusCode, String statusText, @Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { + this(message, HttpStatusCode.valueOf(statusCode), statusText, responseHeaders, responseBody, responseCharset); + } + /** + * Construct a new instance of with the given response data. + * @param statusCode 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 6.0 + */ + public RestClientResponseException(String message, HttpStatusCode statusCode, String statusText, + @Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) { super(message); - this.rawStatusCode = statusCode; + this.statusCode = statusCode; this.statusText = statusText; this.responseHeaders = responseHeaders; this.responseBody = (responseBody != null ? responseBody : new byte[0]); @@ -70,10 +84,20 @@ public class RestClientResponseException extends RestClientException { /** - * Return the raw HTTP status code value. + * Return the HTTP status code. + * @since 6.0 */ + public HttpStatusCode getStatusCode() { + return this.statusCode; + } + + /** + * Return the raw HTTP status code value. + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} + */ + @Deprecated public int getRawStatusCode() { - return this.rawStatusCode; + return this.statusCode.value(); } /** diff --git a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java index 7e27ac62a7..31c7c4224c 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java @@ -33,7 +33,7 @@ import org.springframework.core.SpringProperties; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; @@ -798,9 +798,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat boolean hasError = errorHandler.hasError(response); if (logger.isDebugEnabled()) { try { - int code = response.getRawStatusCode(); - HttpStatus status = HttpStatus.resolve(code); - logger.debug("Response " + (status != null ? status : code)); + HttpStatusCode statusCode = response.getStatusCode(); + logger.debug("Response " + statusCode); } catch (IOException ex) { // ignore @@ -1026,10 +1025,10 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat public ResponseEntity extractData(ClientHttpResponse response) throws IOException { if (this.delegate != null) { T body = this.delegate.extractData(response); - return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(body); + return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(body); } else { - return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).build(); + return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).build(); } } } diff --git a/spring-web/src/main/java/org/springframework/web/client/UnknownContentTypeException.java b/spring-web/src/main/java/org/springframework/web/client/UnknownContentTypeException.java index fca905394c..ce47aedbd8 100644 --- a/spring-web/src/main/java/org/springframework/web/client/UnknownContentTypeException.java +++ b/spring-web/src/main/java/org/springframework/web/client/UnknownContentTypeException.java @@ -20,6 +20,7 @@ import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.lang.Nullable; @@ -40,7 +41,7 @@ public class UnknownContentTypeException extends RestClientException { private final MediaType contentType; - private final int rawStatusCode; + private final HttpStatusCode statusCode; private final String statusText; @@ -61,12 +62,28 @@ public class UnknownContentTypeException extends RestClientException { public UnknownContentTypeException(Type targetType, MediaType contentType, int statusCode, String statusText, HttpHeaders responseHeaders, byte[] responseBody) { + this(targetType, contentType, HttpStatusCode.valueOf(statusCode), statusText, responseHeaders, responseBody); + } + + /** + * Construct a new instance of with the given response data. + * @param targetType the expected target type + * @param contentType the content type of the response + * @param statusCode 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}) + * @since 6.0 + */ + public UnknownContentTypeException(Type targetType, MediaType contentType, + HttpStatusCode statusCode, String statusText, HttpHeaders responseHeaders, byte[] responseBody) { + super("Could not extract response: no suitable HttpMessageConverter found " + "for response type [" + targetType + "] and content type [" + contentType + "]"); this.targetType = targetType; this.contentType = contentType; - this.rawStatusCode = statusCode; + this.statusCode = statusCode; this.statusText = statusText; this.responseHeaders = responseHeaders; this.responseBody = responseBody; @@ -88,10 +105,19 @@ public class UnknownContentTypeException extends RestClientException { } /** - * Return the raw HTTP status code value. + * Return the HTTP status code value. */ + public HttpStatusCode getStatusCode() { + return this.statusCode; + } + + /** + * Return the raw HTTP status code value. + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} + */ + @Deprecated public int getRawStatusCode() { - return this.rawStatusCode; + return this.statusCode.value(); } /** diff --git a/spring-web/src/main/java/org/springframework/web/client/UnknownHttpStatusCodeException.java b/spring-web/src/main/java/org/springframework/web/client/UnknownHttpStatusCodeException.java index c7b0319018..a1676d5302 100644 --- a/spring-web/src/main/java/org/springframework/web/client/UnknownHttpStatusCodeException.java +++ b/spring-web/src/main/java/org/springframework/web/client/UnknownHttpStatusCodeException.java @@ -19,7 +19,6 @@ package org.springframework.web.client; import java.nio.charset.Charset; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.lang.Nullable; /** @@ -34,8 +33,8 @@ public class UnknownHttpStatusCodeException extends RestClientResponseException /** - * Construct a new instance of {@code HttpStatusCodeException} based on an - * {@link HttpStatus}, status text, and response body content. + * Construct a new instance of {@code HttpStatusCodeException} based on a + * status code, 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}) @@ -50,8 +49,8 @@ public class UnknownHttpStatusCodeException extends RestClientResponseException } /** - * Construct a new instance of {@code HttpStatusCodeException} based on an - * {@link HttpStatus}, status text, and response body content. + * Construct a new instance of {@code HttpStatusCodeException} based on a + * status code, 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}) diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/AsyncRequestTimeoutException.java b/spring-web/src/main/java/org/springframework/web/context/request/async/AsyncRequestTimeoutException.java index 0a00eb4078..100dd59303 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/AsyncRequestTimeoutException.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/AsyncRequestTimeoutException.java @@ -17,6 +17,7 @@ package org.springframework.web.context.request.async; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.web.ErrorResponse; @@ -37,13 +38,13 @@ import org.springframework.web.ErrorResponse; public class AsyncRequestTimeoutException extends RuntimeException implements ErrorResponse { @Override - public int getRawStatusCode() { - return HttpStatus.SERVICE_UNAVAILABLE.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.SERVICE_UNAVAILABLE; } @Override public ProblemDetail getBody() { - return ProblemDetail.forRawStatusCode(getRawStatusCode()); + return ProblemDetail.forStatus(getStatusCode()); } } diff --git a/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectFilter.java b/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectFilter.java index 8686852003..d1f204e050 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectFilter.java +++ b/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectFilter.java @@ -24,6 +24,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.util.Assert; /** @@ -43,7 +44,7 @@ import org.springframework.util.Assert; */ public class RelativeRedirectFilter extends OncePerRequestFilter { - private HttpStatus redirectStatus = HttpStatus.SEE_OTHER; + private HttpStatusCode redirectStatus = HttpStatus.SEE_OTHER; /** @@ -51,7 +52,7 @@ public class RelativeRedirectFilter extends OncePerRequestFilter { *

By default this is {@link HttpStatus#SEE_OTHER}. * @param status the 3xx redirect status to use */ - public void setRedirectStatus(HttpStatus status) { + public void setRedirectStatus(HttpStatusCode status) { Assert.notNull(status, "Property 'redirectStatus' is required"); Assert.isTrue(status.is3xxRedirection(), "Not a redirect status code"); this.redirectStatus = status; @@ -60,7 +61,7 @@ public class RelativeRedirectFilter extends OncePerRequestFilter { /** * Return the configured redirect status. */ - public HttpStatus getRedirectStatus() { + public HttpStatusCode getRedirectStatus() { return this.redirectStatus; } diff --git a/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java b/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java index 50777bf220..81c7e3ff7a 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java +++ b/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java @@ -20,7 +20,7 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.util.Assert; import org.springframework.web.util.WebUtils; @@ -33,10 +33,10 @@ import org.springframework.web.util.WebUtils; */ final class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper { - private final HttpStatus redirectStatus; + private final HttpStatusCode redirectStatus; - private RelativeRedirectResponseWrapper(HttpServletResponse response, HttpStatus redirectStatus) { + private RelativeRedirectResponseWrapper(HttpServletResponse response, HttpStatusCode redirectStatus) { super(response); Assert.notNull(redirectStatus, "'redirectStatus' is required"); this.redirectStatus = redirectStatus; @@ -51,7 +51,7 @@ final class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper { public static HttpServletResponse wrapIfNecessary(HttpServletResponse response, - HttpStatus redirectStatus) { + HttpStatusCode redirectStatus) { RelativeRedirectResponseWrapper wrapper = WebUtils.getNativeResponse(response, RelativeRedirectResponseWrapper.class); diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java index 541592c336..62ac9cd048 100644 --- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java @@ -36,7 +36,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.SynthesizingMethodParameter; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -85,7 +85,7 @@ public class HandlerMethod { private final MethodParameter[] parameters; @Nullable - private HttpStatus responseStatus; + private HttpStatusCode responseStatus; @Nullable private String responseStatusReason; @@ -296,7 +296,7 @@ public class HandlerMethod { * @see ResponseStatus#code() */ @Nullable - protected HttpStatus getResponseStatus() { + protected HttpStatusCode getResponseStatus() { return this.responseStatus; } diff --git a/spring-web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java b/spring-web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java index 5cb8d9f71a..1281598a7f 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java @@ -20,7 +20,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; @@ -62,7 +62,7 @@ public class ModelAndViewContainer { private boolean redirectModelScenario = false; @Nullable - private HttpStatus status; + private HttpStatusCode status; private final Set noBinding = new HashSet<>(4); @@ -193,7 +193,7 @@ public class ModelAndViewContainer { * {@code ModelAndView} used for view rendering purposes. * @since 4.3 */ - public void setStatus(@Nullable HttpStatus status) { + public void setStatus(@Nullable HttpStatusCode status) { this.status = status; } @@ -202,7 +202,7 @@ public class ModelAndViewContainer { * @since 4.3 */ @Nullable - public HttpStatus getStatus() { + public HttpStatusCode getStatus() { return this.status; } diff --git a/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java b/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java index 86d07cb086..50b9a6c41b 100644 --- a/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java +++ b/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java @@ -18,7 +18,7 @@ package org.springframework.web.server; import org.springframework.core.NestedExceptionUtils; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.web.ErrorResponseException; @@ -41,7 +41,7 @@ public class ResponseStatusException extends ErrorResponseException { * Constructor with a response status. * @param status the HTTP status (required) */ - public ResponseStatusException(HttpStatus status) { + public ResponseStatusException(HttpStatusCode status) { this(status, null); } @@ -51,21 +51,10 @@ public class ResponseStatusException extends ErrorResponseException { * @param status the HTTP status (required) * @param reason the associated reason (optional) */ - public ResponseStatusException(HttpStatus status, @Nullable String reason) { + public ResponseStatusException(HttpStatusCode status, @Nullable String reason) { this(status, reason, null); } - /** - * Constructor with a response status and a reason to add to the exception - * message as explanation, as well as a nested exception. - * @param status the HTTP status (required) - * @param reason the associated reason (optional) - * @param cause a nested exception (optional) - */ - public ResponseStatusException(HttpStatus status, @Nullable String reason, @Nullable Throwable cause) { - this(status.value(), reason, cause); - } - /** * Constructor with a response status and a reason to add to the exception * message as explanation, as well as a nested exception. @@ -75,7 +64,18 @@ public class ResponseStatusException extends ErrorResponseException { * @since 5.3 */ public ResponseStatusException(int rawStatusCode, @Nullable String reason, @Nullable Throwable cause) { - super(rawStatusCode, cause); + this(HttpStatusCode.valueOf(rawStatusCode), reason, cause); + } + + /** + * Constructor with a response status and a reason to add to the exception + * message as explanation, as well as a nested exception. + * @param status the HTTP status (required) + * @param reason the associated reason (optional) + * @param cause a nested exception (optional) + */ + public ResponseStatusException(HttpStatusCode status, @Nullable String reason, @Nullable Throwable cause) { + super(status, cause); this.reason = reason; } @@ -112,8 +112,7 @@ public class ResponseStatusException extends ErrorResponseException { @Override public String getMessage() { - HttpStatus code = HttpStatus.resolve(getRawStatusCode()); - String msg = (code != null ? code : getRawStatusCode()) + (this.reason != null ? " \"" + this.reason + "\"" : ""); + String msg = getStatusCode() + (this.reason != null ? " \"" + this.reason + "\"" : ""); return NestedExceptionUtils.buildMessage(msg, getCause()); } diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/DefaultServerWebExchange.java b/spring-web/src/main/java/org/springframework/web/server/adapter/DefaultServerWebExchange.java index 984615c6d3..621893f4cf 100644 --- a/spring-web/src/main/java/org/springframework/web/server/adapter/DefaultServerWebExchange.java +++ b/spring-web/src/main/java/org/springframework/web/server/adapter/DefaultServerWebExchange.java @@ -34,6 +34,7 @@ import org.springframework.core.codec.Hints; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.InvalidMediaTypeException; import org.springframework.http.MediaType; import org.springframework.http.codec.HttpMessageReader; @@ -249,7 +250,7 @@ public class DefaultServerWebExchange implements ServerWebExchange { @Override public boolean checkNotModified(@Nullable String etag, Instant lastModified) { - HttpStatus status = getResponse().getStatusCode(); + HttpStatusCode status = getResponse().getStatusCode(); if (this.notModified || (status != null && !HttpStatus.OK.equals(status))) { return this.notModified; } diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java b/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java index 76cae29178..72e9793910 100644 --- a/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java +++ b/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java @@ -29,6 +29,7 @@ import org.springframework.core.NestedExceptionUtils; import org.springframework.core.log.LogFormatUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.codec.LoggingCodecSupport; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.server.reactive.HttpHandler; @@ -270,7 +271,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa private void logResponse(ServerWebExchange exchange) { LogFormatUtils.traceDebug(logger, traceOn -> { - HttpStatus status = exchange.getResponse().getStatusCode(); + HttpStatusCode status = exchange.getResponse().getStatusCode(); return exchange.getLogPrefix() + "Completed " + (status != null ? status : "200 OK") + (traceOn ? ", headers=" + formatHeaders(exchange.getResponse().getHeaders()) : ""); }); diff --git a/spring-web/src/main/java/org/springframework/web/server/handler/ResponseStatusExceptionHandler.java b/spring-web/src/main/java/org/springframework/web/server/handler/ResponseStatusExceptionHandler.java index fb17d47b6f..b155f91129 100644 --- a/spring-web/src/main/java/org/springframework/web/server/handler/ResponseStatusExceptionHandler.java +++ b/spring-web/src/main/java/org/springframework/web/server/handler/ResponseStatusExceptionHandler.java @@ -21,7 +21,7 @@ import org.apache.commons.logging.LogFactory; import reactor.core.publisher.Mono; import org.springframework.core.log.LogFormatUtils; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.lang.Nullable; @@ -88,12 +88,13 @@ public class ResponseStatusExceptionHandler implements WebExceptionHandler { return "Resolved [" + className + ": " + message + "] for HTTP " + request.getMethod() + " " + path; } + @SuppressWarnings("deprecation") private boolean updateResponse(ServerHttpResponse response, Throwable ex) { boolean result = false; - HttpStatus httpStatus = determineStatus(ex); - int code = (httpStatus != null ? httpStatus.value() : determineRawStatusCode(ex)); + HttpStatusCode statusCode = determineStatus(ex); + int code = (statusCode != null ? statusCode.value() : determineRawStatusCode(ex)); if (code != -1) { - if (response.setRawStatusCode(code)) { + if (response.setStatusCode(statusCode)) { if (ex instanceof ResponseStatusException) { ((ResponseStatusException) ex).getHeaders().forEach((name, values) -> values.forEach(value -> response.getHeaders().add(name, value))); @@ -112,16 +113,18 @@ public class ResponseStatusExceptionHandler implements WebExceptionHandler { /** * Determine the HTTP status for the given exception. - *

As of 5.3 this method always returns {@code null} in which case - * {@link #determineRawStatusCode(Throwable)} is used instead. * @param ex the exception to check - * @return the associated HTTP status, if any - * @deprecated as of 5.3 in favor of {@link #determineRawStatusCode(Throwable)}. + * @return the associated HTTP status code, or {@code null} if it can't be + * derived */ @Nullable - @Deprecated - protected HttpStatus determineStatus(Throwable ex) { - return null; + protected HttpStatusCode determineStatus(Throwable ex) { + if (ex instanceof ResponseStatusException responseStatusException) { + return responseStatusException.getStatusCode(); + } + else { + return null; + } } /** @@ -129,10 +132,12 @@ public class ResponseStatusExceptionHandler implements WebExceptionHandler { * @param ex the exception to check * @return the associated HTTP status code, or -1 if it can't be derived. * @since 5.3 + * @deprecated as of 6.0, in favor of {@link #determineStatus(Throwable)} */ + @Deprecated protected int determineRawStatusCode(Throwable ex) { - if (ex instanceof ResponseStatusException) { - return ((ResponseStatusException) ex).getRawStatusCode(); + if (ex instanceof ResponseStatusException responseStatusException) { + return responseStatusException.getStatusCode().value(); } return -1; } diff --git a/spring-web/src/test/java/org/springframework/web/ErrorResponseExceptionTests.java b/spring-web/src/test/java/org/springframework/web/ErrorResponseExceptionTests.java index 949fac4a6d..9ef5acbaf6 100644 --- a/spring-web/src/test/java/org/springframework/web/ErrorResponseExceptionTests.java +++ b/spring-web/src/test/java/org/springframework/web/ErrorResponseExceptionTests.java @@ -328,7 +328,7 @@ public class ErrorResponseExceptionTests { private void assertStatus(ErrorResponse ex, HttpStatus status) { ProblemDetail body = ex.getBody(); - assertThat(ex.getStatus()).isEqualTo(status); + assertThat(ex.getStatusCode()).isEqualTo(status); assertThat(body.getStatus()).isEqualTo(status.value()); assertThat(body.getTitle()).isEqualTo(status.getReasonPhrase()); } diff --git a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java index a56a394880..df7cb10831 100644 --- a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerHttpStatusTests.java @@ -66,7 +66,7 @@ class DefaultResponseErrorHandlerHttpStatusTests { @DisplayName("hasError() returns true") @MethodSource("errorCodes") void hasErrorTrue(HttpStatus httpStatus) throws Exception { - given(this.response.getRawStatusCode()).willReturn(httpStatus.value()); + given(this.response.getStatusCode()).willReturn(httpStatus); assertThat(this.handler.hasError(this.response)).isTrue(); } @@ -77,7 +77,7 @@ class DefaultResponseErrorHandlerHttpStatusTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(this.response.getRawStatusCode()).willReturn(httpStatus.value()); + given(this.response.getStatusCode()).willReturn(httpStatus); given(this.response.getHeaders()).willReturn(headers); assertThatExceptionOfType(expectedExceptionClass).isThrownBy(() -> this.handler.handleError(this.response)); diff --git a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java index a455f7088d..ba6af327ed 100644 --- a/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/DefaultResponseErrorHandlerTests.java @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.util.StreamUtils; @@ -50,13 +51,13 @@ public class DefaultResponseErrorHandlerTests { @Test public void hasErrorTrue() throws Exception { - given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); assertThat(handler.hasError(response)).isTrue(); } @Test public void hasErrorFalse() throws Exception { - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); assertThat(handler.hasError(response)).isFalse(); } @@ -65,7 +66,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); given(response.getStatusText()).willReturn("Not Found"); given(response.getHeaders()).willReturn(headers); given(response.getBody()).willReturn(new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8))); @@ -81,7 +82,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); given(response.getStatusText()).willReturn("Not Found"); given(response.getHeaders()).willReturn(headers); given(response.getBody()).willThrow(new IOException()); @@ -94,7 +95,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); given(response.getStatusText()).willReturn("Not Found"); given(response.getHeaders()).willReturn(headers); @@ -107,7 +108,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(999); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(999)); given(response.getStatusText()).willReturn("Custom status code"); given(response.getHeaders()).willReturn(headers); @@ -119,7 +120,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(999); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(999)); given(response.getStatusText()).willReturn("Custom status code"); given(response.getHeaders()).willReturn(headers); @@ -132,7 +133,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(499); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(499)); given(response.getStatusText()).willReturn("Custom status code"); given(response.getHeaders()).willReturn(headers); @@ -141,7 +142,7 @@ public class DefaultResponseErrorHandlerTests { @Test public void handleErrorForCustomClientError() throws Exception { - int statusCode = 499; + HttpStatusCode statusCode = HttpStatusCode.valueOf(499); String statusText = "Custom status code"; HttpHeaders headers = new HttpHeaders(); @@ -150,7 +151,7 @@ public class DefaultResponseErrorHandlerTests { String responseBody = "Hello World"; TestByteArrayInputStream body = new TestByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)); - given(response.getRawStatusCode()).willReturn(statusCode); + given(response.getStatusCode()).willReturn(statusCode); given(response.getStatusText()).willReturn(statusText); given(response.getHeaders()).willReturn(headers); given(response.getBody()).willReturn(body); @@ -158,13 +159,13 @@ public class DefaultResponseErrorHandlerTests { Throwable throwable = catchThrowable(() -> handler.handleError(response)); // validate exception - assertThat(throwable).isInstanceOf(UnknownHttpStatusCodeException.class); - UnknownHttpStatusCodeException actualUnknownHttpStatusCodeException = (UnknownHttpStatusCodeException) throwable; - assertThat(actualUnknownHttpStatusCodeException.getRawStatusCode()).isEqualTo(statusCode); - assertThat(actualUnknownHttpStatusCodeException.getStatusText()).isEqualTo(statusText); - assertThat(actualUnknownHttpStatusCodeException.getResponseHeaders()).isEqualTo(headers); - assertThat(actualUnknownHttpStatusCodeException.getMessage()).contains(responseBody); - assertThat(actualUnknownHttpStatusCodeException.getResponseBodyAsString()).isEqualTo(responseBody); + assertThat(throwable).isInstanceOf(HttpClientErrorException.class); + HttpClientErrorException actualHttpClientErrorException = (HttpClientErrorException) throwable; + assertThat(actualHttpClientErrorException.getStatusCode()).isEqualTo(statusCode); + assertThat(actualHttpClientErrorException.getStatusText()).isEqualTo(statusText); + assertThat(actualHttpClientErrorException.getResponseHeaders()).isEqualTo(headers); + assertThat(actualHttpClientErrorException.getMessage()).contains(responseBody); + assertThat(actualHttpClientErrorException.getResponseBodyAsString()).isEqualTo(responseBody); } @Test // SPR-17461 @@ -172,7 +173,7 @@ public class DefaultResponseErrorHandlerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_PLAIN); - given(response.getRawStatusCode()).willReturn(599); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(599)); given(response.getStatusText()).willReturn("Custom status code"); given(response.getHeaders()).willReturn(headers); @@ -181,7 +182,7 @@ public class DefaultResponseErrorHandlerTests { @Test public void handleErrorForCustomServerError() throws Exception { - int statusCode = 599; + HttpStatusCode statusCode = HttpStatusCode.valueOf(599); String statusText = "Custom status code"; HttpHeaders headers = new HttpHeaders(); @@ -190,7 +191,7 @@ public class DefaultResponseErrorHandlerTests { String responseBody = "Hello World"; TestByteArrayInputStream body = new TestByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)); - given(response.getRawStatusCode()).willReturn(statusCode); + given(response.getStatusCode()).willReturn(statusCode); given(response.getStatusText()).willReturn(statusText); given(response.getHeaders()).willReturn(headers); given(response.getBody()).willReturn(body); @@ -198,13 +199,13 @@ public class DefaultResponseErrorHandlerTests { Throwable throwable = catchThrowable(() -> handler.handleError(response)); // validate exception - assertThat(throwable).isInstanceOf(UnknownHttpStatusCodeException.class); - UnknownHttpStatusCodeException actualUnknownHttpStatusCodeException = (UnknownHttpStatusCodeException) throwable; - assertThat(actualUnknownHttpStatusCodeException.getRawStatusCode()).isEqualTo(statusCode); - assertThat(actualUnknownHttpStatusCodeException.getStatusText()).isEqualTo(statusText); - assertThat(actualUnknownHttpStatusCodeException.getResponseHeaders()).isEqualTo(headers); - assertThat(actualUnknownHttpStatusCodeException.getMessage()).contains(responseBody); - assertThat(actualUnknownHttpStatusCodeException.getResponseBodyAsString()).isEqualTo(responseBody); + assertThat(throwable).isInstanceOf(HttpServerErrorException.class); + HttpServerErrorException actualHttpServerErrorException = (HttpServerErrorException) throwable; + assertThat(actualHttpServerErrorException.getStatusCode()).isEqualTo(statusCode); + assertThat(actualHttpServerErrorException.getStatusText()).isEqualTo(statusText); + assertThat(actualHttpServerErrorException.getResponseHeaders()).isEqualTo(headers); + assertThat(actualHttpServerErrorException.getMessage()).contains(responseBody); + assertThat(actualHttpServerErrorException.getResponseBodyAsString()).isEqualTo(responseBody); } @Test // SPR-16604 @@ -213,7 +214,7 @@ public class DefaultResponseErrorHandlerTests { headers.setContentType(MediaType.TEXT_PLAIN); TestByteArrayInputStream body = new TestByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)); - given(response.getRawStatusCode()).willReturn(999); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(999)); given(response.getStatusText()).willReturn("Custom status code"); given(response.getHeaders()).willReturn(headers); given(response.getBody()).willReturn(body); diff --git a/spring-web/src/test/java/org/springframework/web/client/ExtractingResponseErrorHandlerTests.java b/spring-web/src/test/java/org/springframework/web/client/ExtractingResponseErrorHandlerTests.java index 622a387343..0d73ecd232 100644 --- a/spring-web/src/test/java/org/springframework/web/client/ExtractingResponseErrorHandlerTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/ExtractingResponseErrorHandlerTests.java @@ -60,13 +60,13 @@ public class ExtractingResponseErrorHandlerTests { @Test public void hasError() throws Exception { - given(this.response.getRawStatusCode()).willReturn(HttpStatus.I_AM_A_TEAPOT.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.I_AM_A_TEAPOT); assertThat(this.errorHandler.hasError(this.response)).isTrue(); - given(this.response.getRawStatusCode()).willReturn(HttpStatus.INTERNAL_SERVER_ERROR.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.INTERNAL_SERVER_ERROR); assertThat(this.errorHandler.hasError(this.response)).isTrue(); - given(this.response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.OK); assertThat(this.errorHandler.hasError(this.response)).isFalse(); } @@ -75,19 +75,19 @@ public class ExtractingResponseErrorHandlerTests { this.errorHandler.setSeriesMapping(Collections .singletonMap(HttpStatus.Series.CLIENT_ERROR, null)); - given(this.response.getRawStatusCode()).willReturn(HttpStatus.I_AM_A_TEAPOT.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.I_AM_A_TEAPOT); assertThat(this.errorHandler.hasError(this.response)).isTrue(); - given(this.response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); assertThat(this.errorHandler.hasError(this.response)).isFalse(); - given(this.response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.OK); assertThat(this.errorHandler.hasError(this.response)).isFalse(); } @Test public void handleErrorStatusMatch() throws Exception { - given(this.response.getRawStatusCode()).willReturn(HttpStatus.I_AM_A_TEAPOT.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.I_AM_A_TEAPOT); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentType(MediaType.APPLICATION_JSON); given(this.response.getHeaders()).willReturn(responseHeaders); @@ -103,7 +103,7 @@ public class ExtractingResponseErrorHandlerTests { @Test public void handleErrorSeriesMatch() throws Exception { - given(this.response.getRawStatusCode()).willReturn(HttpStatus.INTERNAL_SERVER_ERROR.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.INTERNAL_SERVER_ERROR); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentType(MediaType.APPLICATION_JSON); given(this.response.getHeaders()).willReturn(responseHeaders); @@ -119,7 +119,7 @@ public class ExtractingResponseErrorHandlerTests { @Test public void handleNoMatch() throws Exception { - given(this.response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentType(MediaType.APPLICATION_JSON); given(this.response.getHeaders()).willReturn(responseHeaders); @@ -141,7 +141,7 @@ public class ExtractingResponseErrorHandlerTests { this.errorHandler.setSeriesMapping(Collections .singletonMap(HttpStatus.Series.CLIENT_ERROR, null)); - given(this.response.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(this.response.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentType(MediaType.APPLICATION_JSON); given(this.response.getHeaders()).willReturn(responseHeaders); diff --git a/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java b/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java index 3a361737fe..68f064a0ae 100644 --- a/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java @@ -72,7 +72,7 @@ class HttpMessageConverterExtractorTests { @Test void noContent() throws IOException { - given(response.getRawStatusCode()).willReturn(HttpStatus.NO_CONTENT.value()); + given(response.getStatusCode()).willReturn(HttpStatus.NO_CONTENT); Object result = extractor.extractData(response); assertThat(result).isNull(); @@ -80,7 +80,7 @@ class HttpMessageConverterExtractorTests { @Test void notModified() throws IOException { - given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_MODIFIED.value()); + given(response.getStatusCode()).willReturn(HttpStatus.NOT_MODIFIED); Object result = extractor.extractData(response); assertThat(result).isNull(); @@ -88,7 +88,7 @@ class HttpMessageConverterExtractorTests { @Test void informational() throws IOException { - given(response.getRawStatusCode()).willReturn(HttpStatus.CONTINUE.value()); + given(response.getStatusCode()).willReturn(HttpStatus.CONTINUE); Object result = extractor.extractData(response); assertThat(result).isNull(); @@ -97,7 +97,7 @@ class HttpMessageConverterExtractorTests { @Test void zeroContentLength() throws IOException { responseHeaders.setContentLength(0); - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); Object result = extractor.extractData(response); @@ -106,7 +106,7 @@ class HttpMessageConverterExtractorTests { @Test void emptyMessageBody() throws IOException { - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream("".getBytes())); @@ -116,7 +116,7 @@ class HttpMessageConverterExtractorTests { @Test // gh-22265 void nullMessageBody() throws IOException { - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(null); @@ -128,7 +128,7 @@ class HttpMessageConverterExtractorTests { void normal() throws IOException { responseHeaders.setContentType(contentType); String expected = "Foo"; - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream(expected.getBytes())); given(converter.canRead(String.class, contentType)).willReturn(true); @@ -141,7 +141,7 @@ class HttpMessageConverterExtractorTests { @Test void cannotRead() throws IOException { responseHeaders.setContentType(contentType); - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream("Foobar".getBytes())); given(converter.canRead(String.class, contentType)).willReturn(false); @@ -159,7 +159,7 @@ class HttpMessageConverterExtractorTests { GenericHttpMessageConverter converter = mock(GenericHttpMessageConverter.class); HttpMessageConverterExtractor extractor = new HttpMessageConverterExtractor>(type, asList(converter)); - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream(expected.getBytes())); given(converter.canRead(type, null, contentType)).willReturn(true); @@ -172,7 +172,7 @@ class HttpMessageConverterExtractorTests { @Test // SPR-13592 void converterThrowsIOException() throws IOException { responseHeaders.setContentType(contentType); - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream("Foobar".getBytes())); given(converter.canRead(String.class, contentType)).willReturn(true); @@ -185,7 +185,7 @@ class HttpMessageConverterExtractorTests { @Test // SPR-13592 void converterThrowsHttpMessageNotReadableException() throws IOException { responseHeaders.setContentType(contentType); - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream("Foobar".getBytes())); given(converter.canRead(String.class, contentType)).willThrow(HttpMessageNotReadableException.class); @@ -197,7 +197,7 @@ class HttpMessageConverterExtractorTests { @Test void unknownContentTypeExceptionContainsCorrectResponseBody() throws IOException { responseHeaders.setContentType(contentType); - given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getStatusCode()).willReturn(HttpStatus.OK); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream("Foobar".getBytes()) { @Override diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/MockClientHttpResponse.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/MockClientHttpResponse.java index 27098aba69..a2606ceed1 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/MockClientHttpResponse.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/MockClientHttpResponse.java @@ -30,6 +30,7 @@ import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.client.reactive.ClientHttpResponse; @@ -46,7 +47,7 @@ import org.springframework.util.MultiValueMap; */ public class MockClientHttpResponse implements ClientHttpResponse { - private final int status; + private final HttpStatusCode statusCode; private final HttpHeaders headers = new HttpHeaders(); @@ -55,25 +56,25 @@ public class MockClientHttpResponse implements ClientHttpResponse { private Flux body = Flux.empty(); - public MockClientHttpResponse(HttpStatus status) { - Assert.notNull(status, "HttpStatus is required"); - this.status = status.value(); - } - public MockClientHttpResponse(int status) { - Assert.isTrue(status > 99 && status < 1000, "Status must be between 100 and 999"); - this.status = status; + this(HttpStatusCode.valueOf(status)); + } + + public MockClientHttpResponse(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode is required"); + this.statusCode = status; } @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.status); + public HttpStatusCode getStatusCode() { + return this.statusCode; } @Override + @Deprecated public int getRawStatusCode() { - return this.status; + return this.statusCode.value(); } @Override @@ -140,7 +141,11 @@ public class MockClientHttpResponse implements ClientHttpResponse { @Override public String toString() { - HttpStatus code = HttpStatus.resolve(this.status); - return (code != null ? code.name() + "(" + this.status + ")" : "Status (" + this.status + ")") + this.headers; + if (this.statusCode instanceof HttpStatus status) { + return status.name() + "(" + this.statusCode + ")" + this.headers; + } + else { + return "Status (" + this.statusCode + ")" + this.headers; + } } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java index 093de96ba6..508c16c98b 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java @@ -30,7 +30,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; @@ -52,21 +52,18 @@ import org.springframework.web.reactive.function.BodyExtractor; public interface ClientResponse { /** - * Return the HTTP status code as an {@link HttpStatus} enum value. - * @return the HTTP status as an HttpStatus enum value (never {@code null}) - * @throws IllegalArgumentException in case of an unknown HTTP status code - * @since #getRawStatusCode() - * @see HttpStatus#valueOf(int) + * Return the HTTP status code as an {@link HttpStatusCode} value. + * @return the HTTP status as an HttpStatusCode value (never {@code null}) */ - HttpStatus statusCode(); + HttpStatusCode statusCode(); /** - * Return the (potentially non-standard) status code of this response. + * Return the raw status code of this response. * @return the HTTP status as an integer value * @since 5.1 - * @see #statusCode() - * @see HttpStatus#resolve(int) + * @deprecated as of 6.0, in favor of {@link #statusCode()} */ + @Deprecated int rawStatusCode(); /** @@ -238,7 +235,7 @@ public interface ClientResponse { * @param statusCode the status code * @return the created builder */ - static Builder create(HttpStatus statusCode) { + static Builder create(HttpStatusCode statusCode) { return create(statusCode, ExchangeStrategies.withDefaults()); } @@ -248,7 +245,7 @@ public interface ClientResponse { * @param strategies the strategies * @return the created builder */ - static Builder create(HttpStatus statusCode, ExchangeStrategies strategies) { + static Builder create(HttpStatusCode statusCode, ExchangeStrategies strategies) { return new DefaultClientResponseBuilder(strategies).statusCode(statusCode); } @@ -269,7 +266,7 @@ public interface ClientResponse { * @param messageReaders the message readers * @return the created builder */ - static Builder create(HttpStatus statusCode, List> messageReaders) { + static Builder create(HttpStatusCode statusCode, List> messageReaders) { return create(statusCode, new ExchangeStrategies() { @Override public List> messageReaders() { @@ -326,7 +323,7 @@ public interface ClientResponse { * @param statusCode the new status code * @return this builder */ - Builder statusCode(HttpStatus statusCode); + Builder statusCode(HttpStatusCode statusCode); /** * Set the raw status code of the response. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java index 7e768498d2..267f6edcfb 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java @@ -34,6 +34,7 @@ import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; @@ -106,11 +107,12 @@ class DefaultClientResponse implements ClientResponse { } @Override - public HttpStatus statusCode() { + public HttpStatusCode statusCode() { return this.response.getStatusCode(); } @Override + @Deprecated public int rawStatusCode() { return this.response.getRawStatusCode(); } @@ -201,9 +203,8 @@ class DefaultClientResponse implements ClientResponse { .map(bodyBytes -> { HttpRequest request = this.requestSupplier.get(); Charset charset = headers().contentType().map(MimeType::getCharset).orElse(null); - int statusCode = rawStatusCode(); - HttpStatus httpStatus = HttpStatus.resolve(statusCode); - if (httpStatus != null) { + HttpStatusCode statusCode = statusCode(); + if (statusCode instanceof HttpStatus httpStatus) { return WebClientResponseException.create( statusCode, httpStatus.getReasonPhrase(), diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java index 955f9834dc..24e9e555b4 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java @@ -30,6 +30,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.http.client.reactive.ClientHttpResponse; import org.springframework.lang.Nullable; @@ -75,7 +76,7 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder { private final ExchangeStrategies strategies; - private int statusCode = 200; + private HttpStatusCode statusCode = HttpStatus.OK; @Nullable private HttpHeaders headers; @@ -102,7 +103,7 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder { DefaultClientResponseBuilder(ClientResponse other, boolean mutate) { Assert.notNull(other, "ClientResponse must not be null"); this.strategies = other.strategies(); - this.statusCode = other.rawStatusCode(); + this.statusCode = other.statusCode(); if (mutate) { this.body = other.bodyToFlux(DataBuffer.class); } @@ -117,15 +118,15 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder { @Override - public DefaultClientResponseBuilder statusCode(HttpStatus statusCode) { - return rawStatusCode(statusCode.value()); + public DefaultClientResponseBuilder statusCode(HttpStatusCode statusCode) { + Assert.notNull(statusCode, "StatusCode must not be null"); + this.statusCode = statusCode; + return this; } @Override public DefaultClientResponseBuilder rawStatusCode(int statusCode) { - Assert.isTrue(statusCode >= 100 && statusCode < 600, "StatusCode must be between 1xx and 5xx"); - this.statusCode = statusCode; - return this; + return statusCode(HttpStatusCode.valueOf(statusCode)); } @Override @@ -224,7 +225,7 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder { private static class BuiltClientHttpResponse implements ClientHttpResponse { - private final int statusCode; + private final HttpStatusCode statusCode; @Nullable private final HttpHeaders headers; @@ -238,7 +239,7 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder { private final ClientResponse originalResponse; - BuiltClientHttpResponse(int statusCode, @Nullable HttpHeaders headers, + BuiltClientHttpResponse(HttpStatusCode statusCode, @Nullable HttpHeaders headers, @Nullable MultiValueMap cookies, Flux body, @Nullable ClientResponse originalResponse) { @@ -256,13 +257,14 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder { } @Override - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.statusCode); + public HttpStatusCode getStatusCode() { + return this.statusCode; } @Override + @Deprecated public int getRawStatusCode() { - return this.statusCode; + return this.statusCode.value(); } @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java index d6627ce2f6..e7589c41fa 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java @@ -39,7 +39,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.reactive.ClientHttpRequest; @@ -491,7 +491,7 @@ class DefaultWebClient implements WebClient { private static class DefaultResponseSpec implements ResponseSpec { - private static final IntPredicate STATUS_CODE_ERROR = (value -> value >= 400); + private static final Predicate STATUS_CODE_ERROR = HttpStatusCode::isError; private static final StatusHandler DEFAULT_STATUS_HANDLER = new StatusHandler(STATUS_CODE_ERROR, ClientResponse::createException); @@ -511,28 +511,26 @@ class DefaultWebClient implements WebClient { @Override - public ResponseSpec onStatus(Predicate statusPredicate, + public ResponseSpec onStatus(Predicate statusCodePredicate, Function> exceptionFunction) { - return onRawStatus(toIntPredicate(statusPredicate), exceptionFunction); - } + Assert.notNull(statusCodePredicate, "StatusCodePredicate must not be null"); + Assert.notNull(exceptionFunction, "Function must not be null"); + int index = this.statusHandlers.size() - 1; // Default handler always last + this.statusHandlers.add(index, new StatusHandler(statusCodePredicate, exceptionFunction)); + return this; - private static IntPredicate toIntPredicate(Predicate predicate) { - return value -> { - HttpStatus status = HttpStatus.resolve(value); - return (status != null && predicate.test(status)); - }; } @Override public ResponseSpec onRawStatus(IntPredicate statusCodePredicate, Function> exceptionFunction) { - Assert.notNull(statusCodePredicate, "IntPredicate must not be null"); - Assert.notNull(exceptionFunction, "Function must not be null"); - int index = this.statusHandlers.size() - 1; // Default handler always last - this.statusHandlers.add(index, new StatusHandler(statusCodePredicate, exceptionFunction)); - return this; + return onStatus(toStatusCodePredicate(statusCodePredicate), exceptionFunction); + } + + private static Predicate toStatusCodePredicate(IntPredicate predicate) { + return value -> predicate.test(value.value()); } @Override @@ -635,7 +633,7 @@ class DefaultWebClient implements WebClient { ResponseEntity> entity = new ResponseEntity<>( body.onErrorResume(WebClientUtils.WRAP_EXCEPTION_PREDICATE, exceptionWrappingFunction(response)), response.headers().asHttpHeaders(), - response.rawStatusCode()); + response.statusCode()); Mono>> result = applyStatusHandlers(response); return (result != null ? result.defaultIfEmpty(entity) : Mono.just(entity)); @@ -647,7 +645,7 @@ class DefaultWebClient implements WebClient { @Nullable private Mono applyStatusHandlers(ClientResponse response) { - int statusCode = response.rawStatusCode(); + HttpStatusCode statusCode = response.statusCode(); for (StatusHandler handler : this.statusHandlers) { if (handler.test(statusCode)) { Mono exMono; @@ -667,7 +665,7 @@ class DefaultWebClient implements WebClient { return null; } - private Mono insertCheckpoint(Mono result, int statusCode, HttpRequest request) { + private Mono insertCheckpoint(Mono result, HttpStatusCode statusCode, HttpRequest request) { HttpMethod httpMethod = request.getMethod(); URI uri = request.getURI(); String description = statusCode + " from " + httpMethod + " " + uri + " [DefaultWebClient]"; @@ -677,18 +675,18 @@ class DefaultWebClient implements WebClient { private static class StatusHandler { - private final IntPredicate predicate; + private final Predicate predicate; private final Function> exceptionFunction; - public StatusHandler(IntPredicate predicate, + public StatusHandler(Predicate predicate, Function> exceptionFunction) { this.predicate = predicate; this.exceptionFunction = exceptionFunction; } - public boolean test(int status) { + public boolean test(HttpStatusCode status) { return this.predicate.test(status); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java index f79635e5fd..7f55ab0a85 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java @@ -26,7 +26,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -66,12 +66,12 @@ public abstract class ExchangeFilterFunctions { /** * Return a filter that generates an error signal when the given - * {@link HttpStatus} predicate matches. + * {@link HttpStatusCode} predicate matches. * @param statusPredicate the predicate to check the HTTP status with * @param exceptionFunction the function that to create the exception * @return the filter to generate an error signal */ - public static ExchangeFilterFunction statusError(Predicate statusPredicate, + public static ExchangeFilterFunction statusError(Predicate statusPredicate, Function exceptionFunction) { Assert.notNull(statusPredicate, "Predicate must not be null"); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java index b85566ab48..f7a14f4ed3 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java @@ -26,7 +26,6 @@ import org.springframework.core.log.LogFormatUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ClientHttpResponse; import org.springframework.http.codec.LoggingCodecSupport; @@ -125,12 +124,8 @@ public abstract class ExchangeFunctions { } private void logResponse(ClientHttpResponse response, String logPrefix) { - LogFormatUtils.traceDebug(logger, traceOn -> { - int code = response.getRawStatusCode(); - HttpStatus status = HttpStatus.resolve(code); - return logPrefix + "Response " + (status != null ? status : code) + - (traceOn ? ", headers=" + formatHeaders(response.getHeaders()) : ""); - }); + LogFormatUtils.traceDebug(logger, traceOn -> logPrefix + "Response " + response.getStatusCode() + + (traceOn ? ", headers=" + formatHeaders(response.getHeaders()) : "")); } private String formatHeaders(HttpHeaders headers) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/UnknownHttpStatusCodeException.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/UnknownHttpStatusCodeException.java index 07550a11db..34bc91483d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/UnknownHttpStatusCodeException.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/UnknownHttpStatusCodeException.java @@ -20,6 +20,7 @@ import java.nio.charset.Charset; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; /** @@ -57,4 +58,17 @@ public class UnknownHttpStatusCodeException extends WebClientResponseException { headers, responseBody, responseCharset, request); } + /** + * Create a new instance of the {@code UnknownHttpStatusCodeException} with the given + * parameters. + * @since 6.0 + */ + public UnknownHttpStatusCodeException( + HttpStatusCode statusCode, HttpHeaders headers, byte[] responseBody, @Nullable Charset responseCharset, + @Nullable HttpRequest request) { + + super("Unknown status code [" + statusCode + "]", statusCode, "", + headers, responseBody, responseCharset, request); + } + } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java index 3e2fda8bed..6361c9b374 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java @@ -35,7 +35,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.reactive.ClientHttpConnector; @@ -767,7 +767,7 @@ public interface WebClient { * @return this builder * @see ClientResponse#createException() */ - ResponseSpec onStatus(Predicate statusPredicate, + ResponseSpec onStatus(Predicate statusPredicate, Function> exceptionFunction); /** diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientResponseException.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientResponseException.java index 0d5137019b..aa114f4537 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientResponseException.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientResponseException.java @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; /** @@ -35,7 +36,7 @@ public class WebClientResponseException extends WebClientException { private static final long serialVersionUID = 4127543205414951611L; - private final int statusCode; + private final HttpStatusCode statusCode; private final String statusText; @@ -68,11 +69,21 @@ public class WebClientResponseException extends WebClientException { @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset, @Nullable HttpRequest request) { - this(initMessage(status, reasonPhrase, request), status, reasonPhrase, headers, body, charset, request); + this(HttpStatusCode.valueOf(status), reasonPhrase, headers, body, charset, request); } - private static String initMessage(int status, String reasonPhrase, @Nullable HttpRequest request) { - return status + " " + reasonPhrase + + /** + * Constructor with response data only, and a default message. + * @since 6.0 + */ + public WebClientResponseException(HttpStatusCode statusCode, String reasonPhrase, + @Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset, + @Nullable HttpRequest request) { + this(initMessage(statusCode, reasonPhrase, request), statusCode, reasonPhrase, headers, body, charset, request); + } + + private static String initMessage(HttpStatusCode status, String reasonPhrase, @Nullable HttpRequest request) { + return status.value() + " " + reasonPhrase + (request != null ? " from " + request.getMethod() + " " + request.getURI() : ""); } @@ -91,6 +102,17 @@ public class WebClientResponseException extends WebClientException { public WebClientResponseException(String message, int statusCode, String statusText, @Nullable HttpHeaders headers, @Nullable byte[] responseBody, @Nullable Charset charset, @Nullable HttpRequest request) { + this(message, HttpStatusCode.valueOf(statusCode), statusText, headers, responseBody, charset, request); + + + } + /** + * Constructor with a prepared message. + * @since 6.0 + */ + public WebClientResponseException(String message, HttpStatusCode statusCode, String statusText, + @Nullable HttpHeaders headers, @Nullable byte[] responseBody, @Nullable Charset charset, + @Nullable HttpRequest request) { super(message); @@ -107,15 +129,17 @@ public class WebClientResponseException extends WebClientException { * Return the HTTP status code value. * @throws IllegalArgumentException in case of an unknown HTTP status code */ - public HttpStatus getStatusCode() { - return HttpStatus.valueOf(this.statusCode); + public HttpStatusCode getStatusCode() { + return this.statusCode; } /** * Return the raw HTTP status code value. + * @deprecated as of 6.0, in favor of {@link #getStatusCode()} */ + @Deprecated public int getRawStatusCode() { - return this.statusCode; + return this.statusCode.value(); } /** @@ -188,9 +212,18 @@ public class WebClientResponseException extends WebClientException { public static WebClientResponseException create( int statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset, @Nullable HttpRequest request) { + return create(HttpStatusCode.valueOf(statusCode), statusText, headers, body, charset, request); + } - HttpStatus httpStatus = HttpStatus.resolve(statusCode); - if (httpStatus != null) { + /** + * Create {@code WebClientResponseException} or an HTTP status specific subclass. + * @since 6.0 + */ + public static WebClientResponseException create( + HttpStatusCode statusCode, String statusText, HttpHeaders headers, byte[] body, + @Nullable Charset charset, @Nullable HttpRequest request) { + + if (statusCode instanceof HttpStatus httpStatus) { switch (httpStatus) { case BAD_REQUEST: return new WebClientResponseException.BadRequest(statusText, headers, body, charset, request); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java index c234e0e578..dae54ccb13 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java @@ -53,7 +53,7 @@ abstract class WebClientUtils { new ResponseEntity<>( body != VALUE_NONE ? (T) body : null, response.headers().asHttpHeaders(), - response.rawStatusCode())); + response.statusCode())); } /** @@ -61,7 +61,7 @@ abstract class WebClientUtils { */ public static Mono>> mapToEntityList(ClientResponse response, Publisher body) { return Flux.from(body).collectList().map(list -> - new ResponseEntity<>(list, response.headers().asHttpHeaders(), response.rawStatusCode())); + new ResponseEntity<>(list, response.headers().asHttpHeaders(), response.statusCode())); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java index e20f6ff8cb..4152c7474a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java @@ -25,7 +25,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; @@ -74,11 +74,12 @@ public class ClientResponseWrapper implements ClientResponse { } @Override - public HttpStatus statusCode() { + public HttpStatusCode statusCode() { return this.delegate.statusCode(); } @Override + @Deprecated public int rawStatusCode() { return this.delegate.rawStatusCode(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java index 461a82efd2..80a3034a16 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java @@ -35,6 +35,7 @@ import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.codec.HttpMessageWriter; @@ -60,7 +61,7 @@ class DefaultEntityResponseBuilder implements EntityResponse.Builder { private final BodyInserter inserter; - private int status = HttpStatus.OK.value(); + private HttpStatusCode status = HttpStatus.OK; private final HttpHeaders headers = new HttpHeaders(); @@ -76,16 +77,15 @@ class DefaultEntityResponseBuilder implements EntityResponse.Builder { @Override - public EntityResponse.Builder status(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); - this.status = status.value(); + public EntityResponse.Builder status(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); + this.status = status; return this; } @Override public EntityResponse.Builder status(int status) { - this.status = status; - return this; + return status(HttpStatusCode.valueOf(status)); } @Override @@ -209,7 +209,7 @@ class DefaultEntityResponseBuilder implements EntityResponse.Builder { private final BodyInserter inserter; - public DefaultEntityResponse(int statusCode, HttpHeaders headers, + public DefaultEntityResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, T entity, BodyInserter inserter, Map hints) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java index a67ae48653..d8b7f8b8ba 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java @@ -33,6 +33,7 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.Conventions; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; @@ -53,7 +54,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder private final String name; - private int status = HttpStatus.OK.value(); + private HttpStatusCode status = HttpStatus.OK; private final HttpHeaders headers = new HttpHeaders(); @@ -65,8 +66,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder public DefaultRenderingResponseBuilder(RenderingResponse other) { Assert.notNull(other, "RenderingResponse must not be null"); this.name = other.name(); - this.status = (other instanceof DefaultRenderingResponse ? - ((DefaultRenderingResponse) other).statusCode : other.statusCode().value()); + this.status = other.statusCode(); this.headers.putAll(other.headers()); this.model.putAll(other.model()); } @@ -78,16 +78,15 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder @Override - public RenderingResponse.Builder status(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); - this.status = status.value(); + public RenderingResponse.Builder status(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); + this.status = status; return this; } @Override public RenderingResponse.Builder status(int status) { - this.status = status; - return this; + return status(HttpStatusCode.valueOf(status)); } @Override @@ -165,7 +164,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder private final Map model; - public DefaultRenderingResponse(int statusCode, HttpHeaders headers, + public DefaultRenderingResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, String name, Map model) { super(statusCode, headers, cookies, Collections.emptyMap()); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java index 1514af903e..1a0f6c0465 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java @@ -41,6 +41,8 @@ import org.springframework.http.HttpCookie; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRange; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.multipart.Part; @@ -98,8 +100,8 @@ class DefaultServerRequest implements ServerRequest { } if (exchange.checkNotModified(etag, lastModified)) { - Integer statusCode = exchange.getResponse().getRawStatusCode(); - return ServerResponse.status(statusCode != null ? statusCode : 200) + HttpStatusCode statusCode = exchange.getResponse().getStatusCode(); + return ServerResponse.status(statusCode != null ? statusCode : HttpStatus.OK) .headers(headers -> headers.addAll(exchange.getResponse().getHeaders())) .build(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java index b62189c041..93f96ecffc 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java @@ -39,7 +39,7 @@ import org.springframework.core.codec.Hints; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ReactiveHttpOutputMessage; import org.springframework.http.ResponseCookie; @@ -64,7 +64,7 @@ import org.springframework.web.server.ServerWebExchange; */ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { - private final int statusCode; + private final HttpStatusCode statusCode; private final HttpHeaders headers = new HttpHeaders(); @@ -77,22 +77,15 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { Assert.notNull(other, "ServerResponse must not be null"); this.headers.addAll(other.headers()); this.cookies.addAll(other.cookies()); + this.statusCode = other.statusCode(); if (other instanceof AbstractServerResponse abstractOther) { - this.statusCode = abstractOther.statusCode; this.hints.putAll(abstractOther.hints); } - else { - this.statusCode = other.statusCode().value(); - } } - public DefaultServerResponseBuilder(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); - this.statusCode = status.value(); - } - - public DefaultServerResponseBuilder(int statusCode) { - this.statusCode = statusCode; + public DefaultServerResponseBuilder(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); + this.statusCode = status; } @@ -298,7 +291,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { private static final Set SAFE_METHODS = Set.of(HttpMethod.GET, HttpMethod.HEAD); - final int statusCode; + private final HttpStatusCode statusCode; private final HttpHeaders headers; @@ -308,7 +301,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { protected AbstractServerResponse( - int statusCode, HttpHeaders headers, MultiValueMap cookies, + HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, Map hints) { this.statusCode = statusCode; @@ -318,13 +311,14 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { } @Override - public final HttpStatus statusCode() { - return HttpStatus.valueOf(this.statusCode); + public final HttpStatusCode statusCode() { + return this.statusCode; } @Override + @Deprecated public int rawStatusCode() { - return this.statusCode; + return this.statusCode.value(); } @Override @@ -351,7 +345,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { } private void writeStatusAndHeaders(ServerHttpResponse response) { - response.setRawStatusCode(this.statusCode); + response.setStatusCode(this.statusCode); copy(this.headers, response.getHeaders()); copy(this.cookies, response.getCookies()); } @@ -370,7 +364,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { private final BiFunction> writeFunction; - public WriterFunctionResponse(int statusCode, HttpHeaders headers, + public WriterFunctionResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, BiFunction> writeFunction) { @@ -391,7 +385,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { private final BodyInserter inserter; - public BodyInserterResponse(int statusCode, HttpHeaders headers, + public BodyInserterResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, BodyInserter body, Map hints) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/EntityResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/EntityResponse.java index a659e4ee30..f4e02acd1b 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/EntityResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/EntityResponse.java @@ -30,7 +30,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.codec.json.Jackson2CodecSupport; @@ -154,7 +154,7 @@ public interface EntityResponse extends ServerResponse { * @param status the response status * @return this builder */ - Builder status(HttpStatus status); + Builder status(HttpStatusCode status); /** * Set the HTTP status. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RenderingResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RenderingResponse.java index 2b2ff2979c..3b51db3698 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RenderingResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RenderingResponse.java @@ -23,7 +23,7 @@ import java.util.function.Consumer; import reactor.core.publisher.Mono; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.lang.Nullable; import org.springframework.util.MultiValueMap; @@ -134,7 +134,7 @@ public interface RenderingResponse extends ServerResponse { * @param status the response status * @return this builder */ - Builder status(HttpStatus status); + Builder status(HttpStatusCode status); /** * Set the HTTP status. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java index 51c654fd65..35b3197990 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerResponse.java @@ -35,6 +35,7 @@ import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.codec.HttpMessageWriter; @@ -60,19 +61,17 @@ public interface ServerResponse { /** * Return the status code of this response. - * @return the status as an HttpStatus enum value - * @throws IllegalArgumentException in case of an unknown HTTP status code - * @see HttpStatus#valueOf(int) + * @return the status as an HttpStatusCode value */ - HttpStatus statusCode(); + HttpStatusCode statusCode(); /** - * Return the (potentially non-standard) status code of this response. + * Return the status code of this response as integer. * @return the status as an integer * @since 5.2 - * @see #statusCode() - * @see HttpStatus#resolve(int) + * @deprecated as of 6.0, in favor of {@link #statusCode()} */ + @Deprecated int rawStatusCode(); /** @@ -110,7 +109,7 @@ public interface ServerResponse { * @param status the response status * @return the created builder */ - static BodyBuilder status(HttpStatus status) { + static BodyBuilder status(HttpStatusCode status) { return new DefaultServerResponseBuilder(status); } @@ -121,7 +120,7 @@ public interface ServerResponse { * @since 5.0.3 */ static BodyBuilder status(int status) { - return new DefaultServerResponseBuilder(status); + return new DefaultServerResponseBuilder(HttpStatusCode.valueOf(status)); } /** diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/WebFluxResponseStatusExceptionHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/WebFluxResponseStatusExceptionHandler.java index efc2015bea..d37071b13e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/WebFluxResponseStatusExceptionHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/WebFluxResponseStatusExceptionHandler.java @@ -17,6 +17,7 @@ package org.springframework.web.reactive.handler; import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.http.HttpStatusCode; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.server.handler.ResponseStatusExceptionHandler; @@ -37,15 +38,15 @@ import org.springframework.web.server.handler.ResponseStatusExceptionHandler; public class WebFluxResponseStatusExceptionHandler extends ResponseStatusExceptionHandler { @Override - protected int determineRawStatusCode(Throwable ex) { - int status = super.determineRawStatusCode(ex); - if (status == -1) { + protected HttpStatusCode determineStatus(Throwable ex) { + HttpStatusCode statusCode = super.determineStatus(ex); + if (statusCode == null) { ResponseStatus ann = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class); if (ann != null) { - status = ann.code().value(); + statusCode = ann.code(); } } - return status; + return statusCode; } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java index 4a2fee3ef1..7203049f2c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java @@ -33,7 +33,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; @@ -157,7 +157,7 @@ public class InvocableHandlerMethod extends HandlerMethod { return Mono.error(new IllegalStateException(formatInvokeError("Invocation failure", args), ex)); } - HttpStatus status = getResponseStatus(); + HttpStatusCode status = getResponseStatus(); if (status != null) { exchange.getResponse().setStatusCode(status); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java index fd20d1eec3..a4cfad843c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java @@ -30,7 +30,7 @@ import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.ResolvableType; import org.springframework.core.codec.Hints; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.converter.HttpMessageNotWritableException; @@ -152,7 +152,7 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa bestMediaType = selectMediaType(exchange, () -> getMediaTypesFor(elementType)); } catch (NotAcceptableStatusException ex) { - HttpStatus statusCode = exchange.getResponse().getStatusCode(); + HttpStatusCode statusCode = exchange.getResponse().getStatusCode(); if (statusCode != null && statusCode.isError()) { if (logger.isDebugEnabled()) { logger.debug("Ignoring error response content (if any). " + ex.getReason()); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java index 63da6e12ca..3c785ed74a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java @@ -141,7 +141,7 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand httpEntity = (HttpEntity) returnValue; } else if (returnValue instanceof ErrorResponse response) { - httpEntity = new ResponseEntity<>(response.getBody(), response.getHeaders(), response.getRawStatusCode()); + httpEntity = new ResponseEntity<>(response.getBody(), response.getHeaders(), response.getStatusCode()); } else if (returnValue instanceof ProblemDetail detail) { httpEntity = new ResponseEntity<>(returnValue, HttpHeaders.EMPTY, detail.getStatus()); @@ -161,9 +161,8 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand } } - if (httpEntity instanceof ResponseEntity) { - exchange.getResponse().setRawStatusCode( - ((ResponseEntity) httpEntity).getStatusCodeValue()); + if (httpEntity instanceof ResponseEntity responseEntity) { + exchange.getResponse().setStatusCode(responseEntity.getStatusCode()); } HttpHeaders entityHeaders = httpEntity.getHeaders(); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRendering.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRendering.java index a05e653c49..82d139630a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRendering.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRendering.java @@ -20,7 +20,7 @@ import java.util.Collections; import java.util.Map; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.ui.Model; @@ -40,12 +40,12 @@ class DefaultRendering implements Rendering { private final Map model; @Nullable - private final HttpStatus status; + private final HttpStatusCode status; private final HttpHeaders headers; - DefaultRendering(Object view, @Nullable Model model, @Nullable HttpStatus status, @Nullable HttpHeaders headers) { + DefaultRendering(Object view, @Nullable Model model, @Nullable HttpStatusCode status, @Nullable HttpHeaders headers) { this.view = view; this.model = (model != null ? model.asMap() : Collections.emptyMap()); this.status = status; @@ -66,7 +66,7 @@ class DefaultRendering implements Rendering { @Override @Nullable - public HttpStatus status() { + public HttpStatusCode status() { return this.status; } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRenderingBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRenderingBuilder.java index 44772c5bf6..c1d0923e97 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRenderingBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/DefaultRenderingBuilder.java @@ -20,7 +20,7 @@ import java.util.Arrays; import java.util.Map; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; @@ -40,7 +40,7 @@ class DefaultRenderingBuilder implements Rendering.RedirectBuilder { private Model model; @Nullable - private HttpStatus status; + private HttpStatusCode status; @Nullable private HttpHeaders headers; @@ -83,7 +83,7 @@ class DefaultRenderingBuilder implements Rendering.RedirectBuilder { } @Override - public DefaultRenderingBuilder status(HttpStatus status) { + public DefaultRenderingBuilder status(HttpStatusCode status) { this.status = status; return this; } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java index b6e9f11c03..26eaac0484 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java @@ -27,6 +27,7 @@ import java.util.regex.Pattern; import reactor.core.publisher.Mono; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; @@ -56,7 +57,7 @@ public class RedirectView extends AbstractUrlBasedView { private static final Pattern URI_TEMPLATE_VARIABLE_PATTERN = Pattern.compile("\\{([^/]+?)\\}"); - private HttpStatus statusCode = HttpStatus.SEE_OTHER; + private HttpStatusCode statusCode = HttpStatus.SEE_OTHER; private boolean contextRelative = true; @@ -85,7 +86,7 @@ public class RedirectView extends AbstractUrlBasedView { * redirect status code such as {@link HttpStatus#TEMPORARY_REDIRECT} or * {@link HttpStatus#PERMANENT_REDIRECT}. */ - public RedirectView(String redirectUrl, HttpStatus statusCode) { + public RedirectView(String redirectUrl, HttpStatusCode statusCode) { super(redirectUrl); setStatusCode(statusCode); } @@ -96,7 +97,7 @@ public class RedirectView extends AbstractUrlBasedView { * {@link HttpStatus#TEMPORARY_REDIRECT} or * {@link HttpStatus#PERMANENT_REDIRECT}. */ - public void setStatusCode(HttpStatus statusCode) { + public void setStatusCode(HttpStatusCode statusCode) { Assert.isTrue(statusCode.is3xxRedirection(), "Not a redirect status code"); this.statusCode = statusCode; } @@ -104,7 +105,7 @@ public class RedirectView extends AbstractUrlBasedView { /** * Get the redirect status code to use. */ - public HttpStatus getStatusCode() { + public HttpStatusCode getStatusCode() { return this.statusCode; } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Rendering.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Rendering.java index d17a030b52..d77c724ba6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Rendering.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Rendering.java @@ -20,7 +20,7 @@ import java.util.Collection; import java.util.Map; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.ui.Model; @@ -58,7 +58,7 @@ public interface Rendering { * Return the HTTP status to set the response to. */ @Nullable - HttpStatus status(); + HttpStatusCode status(); /** * Return headers to add to the response. @@ -121,7 +121,7 @@ public interface Rendering { /** * Specify the status to use for the response. */ - B status(HttpStatus status); + B status(HttpStatusCode status); /** * Specify a header to add to the response. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java index 430e7bd52c..1aa890fec2 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java @@ -37,7 +37,7 @@ import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.ui.Model; @@ -214,7 +214,7 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport imp } else if (Rendering.class.isAssignableFrom(clazz)) { Rendering render = (Rendering) returnValue; - HttpStatus status = render.status(); + HttpStatusCode status = render.status(); if (status != null) { exchange.getResponse().setStatusCode(status); } @@ -325,7 +325,7 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport imp bestMediaType = selectMediaType(exchange, () -> mediaTypes); } catch (NotAcceptableStatusException ex) { - HttpStatus statusCode = exchange.getResponse().getStatusCode(); + HttpStatusCode statusCode = exchange.getResponse().getStatusCode(); if (statusCode != null && statusCode.isError()) { if (logger.isDebugEnabled()) { logger.debug("Ignoring error response content (if any). " + ex.getReason()); diff --git a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt index f04000ce46..f82a6b8bd9 100644 --- a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt +++ b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt @@ -21,7 +21,7 @@ import kotlinx.coroutines.reactive.awaitSingle import kotlinx.coroutines.reactor.mono import org.springframework.core.io.Resource import org.springframework.http.HttpMethod -import org.springframework.http.HttpStatus +import org.springframework.http.HttpStatusCode import org.springframework.http.MediaType import org.springframework.web.reactive.function.server.RouterFunctions.nest import java.net.URI @@ -660,7 +660,7 @@ class CoRouterFunctionDsl internal constructor (private val init: (CoRouterFunct /** * @see ServerResponse.status */ - fun status(status: HttpStatus) = ServerResponse.status(status) + fun status(status: HttpStatusCode) = ServerResponse.status(status) /** * @see ServerResponse.status diff --git a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt index 5142c59f7f..38e2fbe877 100644 --- a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt +++ b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt @@ -19,6 +19,7 @@ package org.springframework.web.reactive.function.server import org.springframework.core.io.Resource import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus +import org.springframework.http.HttpStatusCode import org.springframework.http.MediaType import reactor.core.publisher.Mono import java.net.URI @@ -725,7 +726,7 @@ class RouterFunctionDsl internal constructor (private val init: RouterFunctionDs * @return the created builder * @since 5.1 */ - fun status(status: HttpStatus): ServerResponse.BodyBuilder = + fun status(status: HttpStatusCode): ServerResponse.BodyBuilder = ServerResponse.status(status) /** diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilderTests.java index 31e336c719..fa7663f444 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilderTests.java @@ -28,12 +28,12 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.web.testfixture.http.client.reactive.MockClientHttpRequest; import org.springframework.web.testfixture.http.client.reactive.MockClientHttpResponse; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** * @author Arjen Poutsma @@ -106,6 +106,6 @@ public class DefaultClientResponseBuilderTests { ClientResponse result = other.mutate().build(); assertThat(result.rawStatusCode()).isEqualTo(499); - assertThatIllegalArgumentException().isThrownBy(result::statusCode); + assertThat(result.statusCode()).isEqualTo(HttpStatusCode.valueOf(499)); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java index 9143688b17..d1a3fa3852 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java @@ -39,6 +39,7 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRange; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; @@ -49,7 +50,6 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.entry; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -233,8 +233,7 @@ public class DefaultClientResponseTests { httpHeaders.setContentType(MediaType.TEXT_PLAIN); given(mockResponse.getHeaders()).willReturn(httpHeaders); - given(mockResponse.getStatusCode()).willThrow(new IllegalArgumentException("999")); - given(mockResponse.getRawStatusCode()).willReturn(999); + given(mockResponse.getStatusCode()).willReturn(HttpStatusCode.valueOf(999)); given(mockResponse.getBody()).willReturn(body); List> messageReaders = Collections @@ -243,8 +242,7 @@ public class DefaultClientResponseTests { ResponseEntity result = defaultClientResponse.toEntity(String.class).block(); assertThat(result.getBody()).isEqualTo("foo"); - assertThatIllegalArgumentException().isThrownBy( - result::getStatusCode); + assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(999)); assertThat(result.getStatusCodeValue()).isEqualTo(999); assertThat(result.getHeaders().getContentType()).isEqualTo(MediaType.TEXT_PLAIN); } @@ -295,8 +293,7 @@ public class DefaultClientResponseTests { httpHeaders.setContentType(MediaType.TEXT_PLAIN); given(mockResponse.getHeaders()).willReturn(httpHeaders); - given(mockResponse.getStatusCode()).willThrow(new IllegalArgumentException("999")); - given(mockResponse.getRawStatusCode()).willReturn(999); + given(mockResponse.getStatusCode()).willReturn(HttpStatusCode.valueOf(999)); given(mockResponse.getBody()).willReturn(body); List> messageReaders = Collections @@ -305,8 +302,7 @@ public class DefaultClientResponseTests { ResponseEntity> result = defaultClientResponse.toEntityList(String.class).block(); assertThat(result.getBody()).isEqualTo(Collections.singletonList("foo")); - assertThatIllegalArgumentException().isThrownBy( - result::getStatusCode); + assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(999)); assertThat(result.getStatusCodeValue()).isEqualTo(999); assertThat(result.getHeaders().getContentType()).isEqualTo(MediaType.TEXT_PLAIN); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultWebClientTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultWebClientTests.java index a33a24c016..89bc58ae69 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultWebClientTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultWebClientTests.java @@ -38,6 +38,7 @@ import org.springframework.core.NamedThreadLocal; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.web.reactive.function.BodyExtractors; @@ -73,6 +74,7 @@ public class DefaultWebClientTests { @BeforeEach public void setup() { ClientResponse mockResponse = mock(ClientResponse.class); + when(mockResponse.statusCode()).thenReturn(HttpStatus.OK); when(mockResponse.bodyToMono(Void.class)).thenReturn(Mono.empty()); given(this.exchangeFunction.exchange(this.captor.capture())).willReturn(Mono.just(mockResponse)); this.builder = WebClient.builder().baseUrl("/base").exchangeFunction(this.exchangeFunction); @@ -414,8 +416,8 @@ public class DefaultWebClientTests { Mono result = this.builder.build().get() .uri("/path") .retrieve() - .onStatus(HttpStatus::is4xxClientError, resp -> Mono.error(new IllegalStateException("1"))) - .onStatus(HttpStatus::is4xxClientError, resp -> Mono.error(new IllegalStateException("2"))) + .onStatus(HttpStatusCode::is4xxClientError, resp -> Mono.error(new IllegalStateException("1"))) + .onStatus(HttpStatusCode::is4xxClientError, resp -> Mono.error(new IllegalStateException("2"))) .bodyToMono(Void.class); StepVerifier.create(result).expectErrorMessage("1").verify(); @@ -428,8 +430,8 @@ public class DefaultWebClientTests { ClientResponse response = ClientResponse.create(HttpStatus.BAD_REQUEST).build(); given(exchangeFunction.exchange(any())).willReturn(Mono.just(response)); - Predicate predicate1 = mock(Predicate.class); - Predicate predicate2 = mock(Predicate.class); + Predicate predicate1 = mock(Predicate.class); + Predicate predicate2 = mock(Predicate.class); given(predicate1.test(HttpStatus.BAD_REQUEST)).willReturn(false); given(predicate2.test(HttpStatus.BAD_REQUEST)).willReturn(false); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java index 1a776ae843..69eeb9fa81 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java @@ -30,6 +30,7 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.web.reactive.function.BodyExtractors; import static java.nio.charset.StandardCharsets.UTF_8; @@ -170,7 +171,7 @@ public class ExchangeFilterFunctionsTests { ExchangeFunction exchange = r -> Mono.just(response); ExchangeFilterFunction errorHandler = ExchangeFilterFunctions.statusError( - HttpStatus::is4xxClientError, r -> new MyException()); + HttpStatusCode::is4xxClientError, r -> new MyException()); Mono result = errorHandler.filter(request, exchange); @@ -186,7 +187,7 @@ public class ExchangeFilterFunctionsTests { given(response.statusCode()).willReturn(HttpStatus.NOT_FOUND); Mono result = ExchangeFilterFunctions - .statusError(HttpStatus::is5xxServerError, req -> new MyException()) + .statusError(HttpStatusCode::is5xxServerError, req -> new MyException()) .filter(request, req -> Mono.just(response)); StepVerifier.create(result) diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java index 30f6620a13..28dd49b99b 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java @@ -64,6 +64,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; @@ -741,7 +742,7 @@ class WebClientIntegrationTests { Mono result = this.webClient.get() .uri("/greeting") .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.just(new MyException("500 error!"))) + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.just(new MyException("500 error!"))) .bodyToMono(String.class); StepVerifier.create(result) @@ -765,7 +766,7 @@ class WebClientIntegrationTests { Mono result = this.webClient.get() .uri("/greeting") .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.just(new MyException("500 error!"))) + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.just(new MyException("500 error!"))) .bodyToMono(new ParameterizedTypeReference() {}); StepVerifier.create(result) @@ -792,7 +793,7 @@ class WebClientIntegrationTests { Mono result = this.webClient.get() .uri("/json") .retrieve() - .onStatus(HttpStatus::isError, + .onStatus(HttpStatusCode::isError, response -> response.bodyToMono(Pojo.class) .flatMap(pojo -> Mono.error(new MyException(pojo.getFoo()))) ) @@ -841,7 +842,7 @@ class WebClientIntegrationTests { Mono result = this.webClient.get() .uri("/greeting") .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty()) + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.empty()) .bodyToMono(String.class); StepVerifier.create(result) @@ -865,7 +866,7 @@ class WebClientIntegrationTests { Flux result = this.webClient.get() .uri("/greeting") .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty()) + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.empty()) .bodyToFlux(String.class); StepVerifier.create(result) @@ -890,7 +891,7 @@ class WebClientIntegrationTests { Mono> result = this.webClient.get() .uri("/").accept(MediaType.APPLICATION_JSON) .retrieve() - .onStatus(HttpStatus::is5xxServerError, response -> Mono.empty())// use normal response + .onStatus(HttpStatusCode::is5xxServerError, response -> Mono.empty())// use normal response .toEntity(String.class); StepVerifier.create(result) diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/RouterFunctionBuilderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/RouterFunctionBuilderTests.java index 12b4b05110..85b22f5659 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/RouterFunctionBuilderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/RouterFunctionBuilderTests.java @@ -27,6 +27,7 @@ import reactor.test.StepVerifier; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest; import org.springframework.web.testfixture.server.MockServerWebExchange; @@ -50,13 +51,12 @@ public class RouterFunctionBuilderTests { MockServerHttpRequest mockRequest = MockServerHttpRequest.get("https://example.com/foo").build(); ServerRequest getRequest = new DefaultServerRequest(MockServerWebExchange.from(mockRequest), Collections.emptyList()); - Mono responseMono = route.route(getRequest) + Mono responseMono = route.route(getRequest) .flatMap(handlerFunction -> handlerFunction.handle(getRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) - .expectNext(200) + .expectNext(HttpStatus.OK) .verifyComplete(); mockRequest = MockServerHttpRequest.head("https://example.com/foo").build(); @@ -65,11 +65,10 @@ public class RouterFunctionBuilderTests { responseMono = route.route(headRequest) .flatMap(handlerFunction -> handlerFunction.handle(headRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) - .expectNext(202) + .expectNext(HttpStatus.ACCEPTED) .verifyComplete(); mockRequest = MockServerHttpRequest.post("https://example.com/"). @@ -79,11 +78,10 @@ public class RouterFunctionBuilderTests { responseMono = route.route(barRequest) .flatMap(handlerFunction -> handlerFunction.handle(barRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) - .expectNext(204) + .expectNext(HttpStatus.NO_CONTENT) .verifyComplete(); mockRequest = MockServerHttpRequest.post("https://example.com/").build(); @@ -92,8 +90,7 @@ public class RouterFunctionBuilderTests { responseMono = route.route(invalidRequest) .flatMap(handlerFunction -> handlerFunction.handle(invalidRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) .verifyComplete(); @@ -112,13 +109,12 @@ public class RouterFunctionBuilderTests { MockServerHttpRequest mockRequest = MockServerHttpRequest.get("https://localhost/resources/response.txt").build(); ServerRequest resourceRequest = new DefaultServerRequest(MockServerWebExchange.from(mockRequest), Collections.emptyList()); - Mono responseMono = route.route(resourceRequest) + Mono responseMono = route.route(resourceRequest) .flatMap(handlerFunction -> handlerFunction.handle(resourceRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) - .expectNext(200) + .expectNext(HttpStatus.OK) .verifyComplete(); mockRequest = MockServerHttpRequest.post("https://localhost/resources/foo.txt").build(); @@ -126,8 +122,7 @@ public class RouterFunctionBuilderTests { responseMono = route.route(invalidRequest) .flatMap(handlerFunction -> handlerFunction.handle(invalidRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) .verifyComplete(); @@ -146,13 +141,12 @@ public class RouterFunctionBuilderTests { MockServerHttpRequest mockRequest = MockServerHttpRequest.get("https://localhost/foo/bar/baz").build(); ServerRequest fooRequest = new DefaultServerRequest(MockServerWebExchange.from(mockRequest), Collections.emptyList()); - Mono responseMono = route.route(fooRequest) + Mono responseMono = route.route(fooRequest) .flatMap(handlerFunction -> handlerFunction.handle(fooRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(responseMono) - .expectNext(200) + .expectNext(HttpStatus.OK) .verifyComplete(); } @@ -201,13 +195,12 @@ public class RouterFunctionBuilderTests { mockRequest = MockServerHttpRequest.get("https://localhost/bar").build(); ServerRequest barRequest = new DefaultServerRequest(MockServerWebExchange.from(mockRequest), Collections.emptyList()); - Mono barResponseMono = route.route(barRequest) + Mono barResponseMono = route.route(barRequest) .flatMap(handlerFunction -> handlerFunction.handle(barRequest)) - .map(ServerResponse::statusCode) - .map(HttpStatus::value); + .map(ServerResponse::statusCode); StepVerifier.create(barResponseMono) - .expectNext(500) + .expectNext(HttpStatus.INTERNAL_SERVER_ERROR) .verifyComplete(); } @@ -222,7 +215,7 @@ public class RouterFunctionBuilderTests { MockServerHttpRequest mockRequest = MockServerHttpRequest.get("https://example.com/error").build(); ServerRequest serverRequest = new DefaultServerRequest(MockServerWebExchange.from(mockRequest), Collections.emptyList()); - Mono responseStatus = route.route(serverRequest) + Mono responseStatus = route.route(serverRequest) .flatMap(handlerFunction -> handlerFunction.handle(serverRequest)) .map(ServerResponse::statusCode); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/support/DispatcherHandlerIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/support/DispatcherHandlerIntegrationTests.java index 4d5b014046..4b1ef6c241 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/support/DispatcherHandlerIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/server/support/DispatcherHandlerIntegrationTests.java @@ -21,6 +21,7 @@ import reactor.core.publisher.Mono; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.server.reactive.HttpHandler; @@ -63,7 +64,7 @@ class DispatcherHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTe ResponseEntity result = this.restTemplate .getForEntity("http://localhost:" + this.port + "/foo/bar", String.class); - assertThat(result.getStatusCodeValue()).isEqualTo(200); + assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java index c213b1672a..e896404ac8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java @@ -329,7 +329,7 @@ public class ResourceWebHandlerTests { StepVerifier.create(handler.handle(exchange)) .expectErrorSatisfies(err -> { assertThat(err).isInstanceOf(ResponseStatusException.class); - assertThat(((ResponseStatusException) err).getRawStatusCode()).isEqualTo(404); + assertThat(((ResponseStatusException) err).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); }).verify(TIMEOUT); } @@ -375,7 +375,7 @@ public class ResourceWebHandlerTests { StepVerifier.create(this.handler.handle(exchange)) .expectErrorSatisfies(err -> { assertThat(err).isInstanceOf(ResponseStatusException.class); - assertThat(((ResponseStatusException) err).getRawStatusCode()).isEqualTo(404); + assertThat(((ResponseStatusException) err).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); }) .verify(TIMEOUT); if (!location.createRelative(requestPath).exists() && !requestPath.contains(":")) { @@ -470,7 +470,7 @@ public class ResourceWebHandlerTests { StepVerifier.create(this.handler.handle(exchange)) .expectErrorSatisfies(err -> { assertThat(err).isInstanceOf(ResponseStatusException.class); - assertThat(((ResponseStatusException) err).getRawStatusCode()).isEqualTo(404); + assertThat(((ResponseStatusException) err).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); }).verify(TIMEOUT); } @@ -481,7 +481,7 @@ public class ResourceWebHandlerTests { StepVerifier.create(this.handler.handle(exchange)) .expectErrorSatisfies(err -> { assertThat(err).isInstanceOf(ResponseStatusException.class); - assertThat(((ResponseStatusException) err).getRawStatusCode()).isEqualTo(404); + assertThat(((ResponseStatusException) err).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); }).verify(TIMEOUT); } @@ -492,7 +492,7 @@ public class ResourceWebHandlerTests { StepVerifier.create(this.handler.handle(exchange)) .expectErrorSatisfies(err -> { assertThat(err).isInstanceOf(ResponseStatusException.class); - assertThat(((ResponseStatusException) err).getRawStatusCode()).isEqualTo(404); + assertThat(((ResponseStatusException) err).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); }).verify(TIMEOUT); } @@ -527,7 +527,7 @@ public class ResourceWebHandlerTests { StepVerifier.create(mono) .expectErrorSatisfies(err -> { assertThat(err).isInstanceOf(ResponseStatusException.class); - assertThat(((ResponseStatusException) err).getRawStatusCode()).isEqualTo(404); + assertThat(((ResponseStatusException) err).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); }).verify(TIMEOUT); // SPR-17475 diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java index 7acff0afd1..c6039b06c8 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java @@ -29,6 +29,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; @@ -103,7 +104,7 @@ class RequestMappingExceptionHandlingIntegrationTests extends AbstractRequestMap assertThatExceptionOfType(HttpStatusCodeException.class).isThrownBy(() -> performGet("/SPR-16318", headers, String.class).getBody()) .satisfies(ex -> { - assertThat(ex.getRawStatusCode()).isEqualTo(500); + assertThat(ex.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); assertThat(ex.getResponseHeaders().getContentType().toString()).isEqualTo("application/problem+json"); assertThat(ex.getResponseBodyAsString()).isEqualTo("{\"reason\":\"error\"}"); }); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/ZeroDemandResponse.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/ZeroDemandResponse.java index d0bd3bd6b5..b543447e1e 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/ZeroDemandResponse.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/ZeroDemandResponse.java @@ -27,7 +27,7 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.testfixture.io.buffer.LeakAwareDataBufferFactory; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseCookie; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.MultiValueMap; @@ -72,12 +72,12 @@ public class ZeroDemandResponse implements ServerHttpResponse { @Override - public boolean setStatusCode(HttpStatus status) { + public boolean setStatusCode(HttpStatusCode status) { throw new UnsupportedOperationException(); } @Override - public HttpStatus getStatusCode() { + public HttpStatusCode getStatusCode() { throw new UnsupportedOperationException(); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java index da918c257e..7759527b26 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java @@ -48,7 +48,7 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -1125,8 +1125,8 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic logger.debug("Exiting from \"" + dispatchType + "\" dispatch, status " + status + headers); } else { - HttpStatus httpStatus = HttpStatus.resolve(status); - logger.debug("Completed " + (httpStatus != null ? httpStatus : status) + headers); + HttpStatusCode httpStatus = HttpStatusCode.valueOf(status); + logger.debug("Completed " + httpStatus + headers); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/ModelAndView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/ModelAndView.java index b10775cf81..12954130a0 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/ModelAndView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/ModelAndView.java @@ -18,7 +18,7 @@ package org.springframework.web.servlet; import java.util.Map; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.ui.ModelMap; import org.springframework.util.CollectionUtils; @@ -56,7 +56,7 @@ public class ModelAndView { /** Optional HTTP status for the response. */ @Nullable - private HttpStatus status; + private HttpStatusCode status; /** Indicates whether or not this instance has been cleared with a call to {@link #clear()}. */ private boolean cleared = false; @@ -132,7 +132,7 @@ public class ModelAndView { * (to be set just prior to View rendering) * @since 4.3.8 */ - public ModelAndView(String viewName, HttpStatus status) { + public ModelAndView(String viewName, HttpStatusCode status) { this.view = viewName; this.status = status; } @@ -148,7 +148,7 @@ public class ModelAndView { * (to be set just prior to View rendering) * @since 4.3 */ - public ModelAndView(@Nullable String viewName, @Nullable Map model, @Nullable HttpStatus status) { + public ModelAndView(@Nullable String viewName, @Nullable Map model, @Nullable HttpStatusCode status) { this.view = viewName; if (model != null) { getModelMap().addAllAttributes(model); @@ -264,7 +264,7 @@ public class ModelAndView { *

The response status is set just prior to View rendering. * @since 4.3 */ - public void setStatus(@Nullable HttpStatus status) { + public void setStatus(@Nullable HttpStatusCode status) { this.status = status; } @@ -273,7 +273,7 @@ public class ModelAndView { * @since 4.3 */ @Nullable - public HttpStatus getStatus() { + public HttpStatusCode getStatus() { return this.status; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/NoHandlerFoundException.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/NoHandlerFoundException.java index 7673a7b301..3efd0bf9c0 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/NoHandlerFoundException.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/NoHandlerFoundException.java @@ -22,6 +22,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.web.ErrorResponse; @@ -59,13 +60,12 @@ public class NoHandlerFoundException extends ServletException implements ErrorRe this.httpMethod = httpMethod; this.requestURL = requestURL; this.headers = headers; - this.body = ProblemDetail.forRawStatusCode(getRawStatusCode()).withDetail(getMessage()); + this.body = ProblemDetail.forStatus(getStatusCode()).withDetail(getMessage()); } - @Override - public int getRawStatusCode() { - return HttpStatus.NOT_FOUND.value(); + public HttpStatusCode getStatusCode() { + return HttpStatus.NOT_FOUND; } public String getHttpMethod() { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java index b2109def5d..118f723fcf 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java @@ -27,7 +27,7 @@ import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; import org.springframework.web.servlet.mvc.ParameterizableViewController; @@ -74,10 +74,10 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser { RootBeanDefinition controller = new RootBeanDefinition(ParameterizableViewController.class); controller.setSource(source); - HttpStatus statusCode = null; + HttpStatusCode statusCode = null; if (element.hasAttribute("status-code")) { int statusValue = Integer.parseInt(element.getAttribute("status-code")); - statusCode = HttpStatus.valueOf(statusValue); + statusCode = HttpStatusCode.valueOf(statusValue); } String name = element.getLocalName(); @@ -130,7 +130,7 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser { return beanDef; } - private RootBeanDefinition getRedirectView(Element element, @Nullable HttpStatus status, @Nullable Object source) { + private RootBeanDefinition getRedirectView(Element element, @Nullable HttpStatusCode status, @Nullable Object source) { RootBeanDefinition redirectView = new RootBeanDefinition(RedirectView.class); redirectView.setSource(source); redirectView.getConstructorArgumentValues().addIndexedArgumentValue(0, element.getAttribute("redirect-url")); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/RedirectViewControllerRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/RedirectViewControllerRegistration.java index fb015a7c57..876956dd71 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/RedirectViewControllerRegistration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/RedirectViewControllerRegistration.java @@ -17,7 +17,7 @@ package org.springframework.web.servlet.config.annotation; import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.servlet.mvc.ParameterizableViewController; @@ -53,7 +53,7 @@ public class RedirectViewControllerRegistration { *

If not set, {@link org.springframework.web.servlet.view.RedirectView} * will select {@code HttpStatus.MOVED_TEMPORARILY (302)} by default. */ - public RedirectViewControllerRegistration setStatusCode(HttpStatus statusCode) { + public RedirectViewControllerRegistration setStatusCode(HttpStatusCode statusCode) { Assert.isTrue(statusCode.is3xxRedirection(), "Not a redirect status code"); this.redirectView.setStatusCode(statusCode); return this; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistration.java index 3a46802903..42dd2ef1a7 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistration.java @@ -17,7 +17,7 @@ package org.springframework.web.servlet.config.annotation; import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.servlet.RequestToViewNameTranslator; @@ -47,7 +47,7 @@ public class ViewControllerRegistration { * Set the status code to set on the response. Optional. *

If not set the response status will be 200 (OK). */ - public ViewControllerRegistration setStatusCode(HttpStatus statusCode) { + public ViewControllerRegistration setStatusCode(HttpStatusCode statusCode) { this.controller.setStatusCode(statusCode); return this; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java index 1bfdd3d65c..9189a8b1a5 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.Map; import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.AntPathMatcher; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; @@ -104,7 +104,7 @@ public class ViewControllerRegistry { * {@link PathPattern} more tailored for web usage and more efficient. * @since 4.1 */ - public void addStatusController(String urlPath, HttpStatus statusCode) { + public void addStatusController(String urlPath, HttpStatusCode statusCode) { ViewControllerRegistration registration = new ViewControllerRegistration(urlPath); registration.setApplicationContext(this.applicationContext); registration.setStatusCode(statusCode); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java index fc667124db..3e84e8194f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java @@ -27,7 +27,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; @@ -45,14 +45,14 @@ abstract class AbstractServerResponse extends ErrorHandlingServerResponse { private static final Set SAFE_METHODS = Set.of(HttpMethod.GET, HttpMethod.HEAD); - final int statusCode; + private final HttpStatusCode statusCode; private final HttpHeaders headers; private final MultiValueMap cookies; protected AbstractServerResponse( - int statusCode, HttpHeaders headers, MultiValueMap cookies) { + HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies) { this.statusCode = statusCode; this.headers = HttpHeaders.readOnlyHttpHeaders(headers); @@ -61,13 +61,14 @@ abstract class AbstractServerResponse extends ErrorHandlingServerResponse { } @Override - public final HttpStatus statusCode() { - return HttpStatus.valueOf(this.statusCode); + public final HttpStatusCode statusCode() { + return this.statusCode; } @Override + @Deprecated public int rawStatusCode() { - return this.statusCode; + return this.statusCode.value(); } @Override @@ -104,7 +105,7 @@ abstract class AbstractServerResponse extends ErrorHandlingServerResponse { } private void writeStatusAndHeaders(HttpServletResponse response) { - response.setStatus(this.statusCode); + response.setStatus(this.statusCode.value()); writeHeaders(response); writeCookies(response); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultAsyncServerResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultAsyncServerResponse.java index 73e91e507b..975fcfb341 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultAsyncServerResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultAsyncServerResponse.java @@ -34,7 +34,7 @@ import org.reactivestreams.Publisher; import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -83,11 +83,12 @@ final class DefaultAsyncServerResponse extends ErrorHandlingServerResponse imple } @Override - public HttpStatus statusCode() { + public HttpStatusCode statusCode() { return delegate(ServerResponse::statusCode); } @Override + @Deprecated public int rawStatusCode() { return delegate(ServerResponse::rawStatusCode); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilder.java index 68326e0027..2bed63dce8 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilder.java @@ -50,6 +50,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRange; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.InvalidMediaTypeException; import org.springframework.http.MediaType; import org.springframework.http.converter.GenericHttpMessageConverter; @@ -80,7 +81,7 @@ final class DefaultEntityResponseBuilder implements EntityResponse.Builder private final Type entityType; - private int status = HttpStatus.OK.value(); + private HttpStatusCode status = HttpStatus.OK; private final HttpHeaders headers = new HttpHeaders(); @@ -93,16 +94,15 @@ final class DefaultEntityResponseBuilder implements EntityResponse.Builder } @Override - public EntityResponse.Builder status(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); - this.status = status.value(); + public EntityResponse.Builder status(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); + this.status = status; return this; } @Override public EntityResponse.Builder status(int status) { - this.status = status; - return this; + return status(HttpStatusCode.valueOf(status)); } @Override @@ -241,7 +241,7 @@ final class DefaultEntityResponseBuilder implements EntityResponse.Builder private final Type entityType; - public DefaultEntityResponse(int statusCode, HttpHeaders headers, + public DefaultEntityResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, T entity, Type entityType) { super(statusCode, headers, cookies); @@ -347,7 +347,7 @@ final class DefaultEntityResponseBuilder implements EntityResponse.Builder */ private static class CompletionStageEntityResponse extends DefaultEntityResponse> { - public CompletionStageEntityResponse(int statusCode, HttpHeaders headers, + public CompletionStageEntityResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, CompletionStage entity, Type entityType) { super(statusCode, headers, cookies, entity, entityType); @@ -401,7 +401,7 @@ final class DefaultEntityResponseBuilder implements EntityResponse.Builder */ private static class PublisherEntityResponse extends DefaultEntityResponse> { - public PublisherEntityResponse(int statusCode, HttpHeaders headers, + public PublisherEntityResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, Publisher entity, Type entityType) { super(statusCode, headers, cookies, entity, entityType); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultRenderingResponseBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultRenderingResponseBuilder.java index db34f733cf..2f610350db 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultRenderingResponseBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultRenderingResponseBuilder.java @@ -30,6 +30,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.core.Conventions; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; @@ -46,7 +47,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder private final String name; - private int status = HttpStatus.OK.value(); + private HttpStatusCode status = HttpStatus.OK; private final HttpHeaders headers = new HttpHeaders(); @@ -58,8 +59,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder public DefaultRenderingResponseBuilder(RenderingResponse other) { Assert.notNull(other, "RenderingResponse must not be null"); this.name = other.name(); - this.status = (other instanceof DefaultRenderingResponse ? - ((DefaultRenderingResponse) other).statusCode : other.statusCode().value()); + this.status = other.statusCode(); this.headers.putAll(other.headers()); this.model.putAll(other.model()); } @@ -71,16 +71,15 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder @Override - public RenderingResponse.Builder status(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); - this.status = status.value(); + public RenderingResponse.Builder status(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); + this.status = status; return this; } @Override public RenderingResponse.Builder status(int status) { - this.status = status; - return this; + return status(HttpStatusCode.valueOf(status)); } @Override @@ -156,7 +155,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder private final Map model; - public DefaultRenderingResponse(int statusCode, HttpHeaders headers, + public DefaultRenderingResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, String name, Map model) { super(statusCode, headers, cookies); @@ -178,14 +177,7 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder protected ModelAndView writeToInternal(HttpServletRequest request, HttpServletResponse response, Context context) { - HttpStatus status = HttpStatus.resolve(this.statusCode); - ModelAndView mav; - if (status != null) { - mav = new ModelAndView(this.name, status); - } - else { - mav = new ModelAndView(this.name); - } + ModelAndView mav = new ModelAndView(this.name, this.statusCode()); mav.addAllObjects(this.model); return mav; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java index 7cbb36ff99..b5567ff2e2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java @@ -34,7 +34,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; @@ -49,7 +49,7 @@ import org.springframework.web.servlet.ModelAndView; */ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { - private final int statusCode; + private final HttpStatusCode statusCode; private final HttpHeaders headers = new HttpHeaders(); @@ -58,19 +58,14 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { public DefaultServerResponseBuilder(ServerResponse other) { Assert.notNull(other, "ServerResponse must not be null"); - this.statusCode = (other instanceof AbstractServerResponse ? - ((AbstractServerResponse) other).statusCode : other.statusCode().value()); + this.statusCode = other.statusCode(); this.headers.addAll(other.headers()); this.cookies.addAll(other.cookies()); } - public DefaultServerResponseBuilder(HttpStatus status) { - Assert.notNull(status, "HttpStatus must not be null"); - this.statusCode = status.value(); - } - - public DefaultServerResponseBuilder(int statusCode) { - this.statusCode = statusCode; + public DefaultServerResponseBuilder(HttpStatusCode status) { + Assert.notNull(status, "HttpStatusCode must not be null"); + this.statusCode = status; } @Override @@ -221,7 +216,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { private final BiFunction writeFunction; - public WriterFunctionResponse(int statusCode, HttpHeaders headers, MultiValueMap cookies, + public WriterFunctionResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, BiFunction writeFunction) { super(statusCode, headers, cookies); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/EntityResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/EntityResponse.java index 56e033e747..688b62a44c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/EntityResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/EntityResponse.java @@ -28,7 +28,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.util.MultiValueMap; @@ -102,7 +102,7 @@ public interface EntityResponse extends ServerResponse { * @param status the response status * @return this builder */ - Builder status(HttpStatus status); + Builder status(HttpStatusCode status); /** * Set the HTTP status. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RenderingResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RenderingResponse.java index 83e727067e..446dba2cfe 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RenderingResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RenderingResponse.java @@ -23,7 +23,7 @@ import java.util.function.Consumer; import jakarta.servlet.http.Cookie; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.MultiValueMap; @@ -135,7 +135,7 @@ public interface RenderingResponse extends ServerResponse { * @param status the response status * @return this builder */ - Builder status(HttpStatus status); + Builder status(HttpStatusCode status); /** * Set the HTTP status. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java index 6d27928cb7..22fc2dbafb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java @@ -42,6 +42,7 @@ import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.lang.Nullable; @@ -60,18 +61,16 @@ public interface ServerResponse { /** * Return the status code of this response. - * @return the status as an HttpStatus enum value - * @throws IllegalArgumentException in case of an unknown HTTP status code - * @see HttpStatus#valueOf(int) + * @return the status as an HttpStatusCode value */ - HttpStatus statusCode(); + HttpStatusCode statusCode(); /** - * Return the (potentially non-standard) status code of this response. + * Return the status code of this response as integer. * @return the status as an integer - * @see #statusCode() - * @see HttpStatus#valueOf(int) + * @deprecated as of 6.0, in favor of {@link #statusCode()} */ + @Deprecated int rawStatusCode(); /** @@ -112,7 +111,7 @@ public interface ServerResponse { * @param status the response status * @return the created builder */ - static BodyBuilder status(HttpStatus status) { + static BodyBuilder status(HttpStatusCode status) { return new DefaultServerResponseBuilder(status); } @@ -122,7 +121,7 @@ public interface ServerResponse { * @return the created builder */ static BodyBuilder status(int status) { - return new DefaultServerResponseBuilder(status); + return new DefaultServerResponseBuilder(HttpStatusCode.valueOf(status)); } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/SseServerResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/SseServerResponse.java index a3965a0a1c..3e7068278e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/SseServerResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/SseServerResponse.java @@ -31,6 +31,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.DelegatingServerHttpResponse; @@ -59,7 +60,7 @@ final class SseServerResponse extends AbstractServerResponse { private SseServerResponse(Consumer sseConsumer, @Nullable Duration timeout) { - super(200, createHeaders(), emptyCookies()); + super(HttpStatus.OK, createHeaders(), emptyCookies()); this.sseConsumer = sseConsumer; this.timeout = timeout; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java index dd43a0ae3a..ac55f909d1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/ParameterizableViewController.java @@ -21,6 +21,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; @@ -42,7 +43,7 @@ public class ParameterizableViewController extends AbstractController { private Object view; @Nullable - private HttpStatus statusCode; + private HttpStatusCode statusCode; private boolean statusOnly; @@ -108,7 +109,7 @@ public class ParameterizableViewController extends AbstractController { * fully handled within the controller. * @since 4.1 */ - public void setStatusCode(@Nullable HttpStatus statusCode) { + public void setStatusCode(@Nullable HttpStatusCode statusCode) { this.statusCode = statusCode; } @@ -117,7 +118,7 @@ public class ParameterizableViewController extends AbstractController { * @since 4.1 */ @Nullable - public HttpStatus getStatusCode() { + public HttpStatusCode getStatusCode() { return this.statusCode; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java index 94950f9e2d..59e5caa36a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java @@ -131,7 +131,7 @@ public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionRes HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws Exception { ex.getHeaders().forEach((name, values) -> values.forEach(value -> response.addHeader(name, value))); - return applyStatusAndReason(ex.getRawStatusCode(), ex.getReason(), response); + return applyStatusAndReason(ex.getStatusCode().value(), ex.getReason(), response); } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index 620f451512..50c29b00a5 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -33,7 +33,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.SpringProperties; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; @@ -442,7 +442,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce } else { ModelMap model = mavContainer.getModel(); - HttpStatus status = mavContainer.getStatus(); + HttpStatusCode status = mavContainer.getStatus(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status); mav.setViewName(mavContainer.getViewName()); if (!mavContainer.isViewReference()) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java index b194b5dcf7..81d8bc24ea 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java @@ -182,7 +182,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro HttpEntity httpEntity; if (returnValue instanceof ErrorResponse response) { - httpEntity = new ResponseEntity<>(response.getBody(), response.getHeaders(), response.getRawStatusCode()); + httpEntity = new ResponseEntity<>(response.getBody(), response.getHeaders(), response.getStatusCode()); } else if (returnValue instanceof ProblemDetail detail) { httpEntity = new ResponseEntity<>(returnValue, HttpHeaders.EMPTY, detail.getStatus()); @@ -216,7 +216,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro } if (httpEntity instanceof ResponseEntity responseEntity) { - int returnStatus = responseEntity.getStatusCodeValue(); + int returnStatus = responseEntity.getStatusCode().value(); outputMessage.getServletResponse().setStatus(returnStatus); if (returnStatus == 200) { HttpMethod method = inputMessage.getMethod(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java index f6550aed27..3e799b544d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java @@ -130,9 +130,8 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur Assert.state(response != null, "No HttpServletResponse"); ServerHttpResponse outputMessage = new ServletServerHttpResponse(response); - if (returnValue instanceof ResponseEntity) { - ResponseEntity responseEntity = (ResponseEntity) returnValue; - response.setStatus(responseEntity.getStatusCodeValue()); + if (returnValue instanceof ResponseEntity responseEntity) { + response.setStatus(responseEntity.getStatusCode().value()); outputMessage.getHeaders().putAll(responseEntity.getHeaders()); returnValue = responseEntity.getBody(); returnType = returnType.nested(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java index c5ac497212..9aac2e3c72 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java @@ -24,6 +24,7 @@ import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.TypeMismatchException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -124,62 +125,57 @@ public abstract class ResponseEntityExceptionHandler { if (ex instanceof ErrorResponse errorEx) { if (ex instanceof HttpRequestMethodNotSupportedException subEx) { - return handleHttpRequestMethodNotSupported(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleHttpRequestMethodNotSupported(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof HttpMediaTypeNotSupportedException subEx) { - return handleHttpMediaTypeNotSupported(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleHttpMediaTypeNotSupported(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof HttpMediaTypeNotAcceptableException subEx) { - return handleHttpMediaTypeNotAcceptable(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleHttpMediaTypeNotAcceptable(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof MissingPathVariableException subEx) { - return handleMissingPathVariable(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleMissingPathVariable(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof MissingServletRequestParameterException subEx) { - return handleMissingServletRequestParameter(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleMissingServletRequestParameter(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof MissingServletRequestPartException subEx) { - return handleMissingServletRequestPart(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleMissingServletRequestPart(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof ServletRequestBindingException subEx) { - return handleServletRequestBindingException(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleServletRequestBindingException(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof MethodArgumentNotValidException subEx) { - return handleMethodArgumentNotValid(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleMethodArgumentNotValid(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof NoHandlerFoundException subEx) { - return handleNoHandlerFoundException(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleNoHandlerFoundException(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else if (ex instanceof AsyncRequestTimeoutException subEx) { - return handleAsyncRequestTimeoutException(subEx, subEx.getHeaders(), subEx.getStatus(), request); + return handleAsyncRequestTimeoutException(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } else { // Another ErrorResponseException - return handleExceptionInternal(ex, null, errorEx.getHeaders(), errorEx.getStatus(), request); + return handleExceptionInternal(ex, null, errorEx.getHeaders(), errorEx.getStatusCode(), request); } } // Other, lower level exceptions - if (ex instanceof ConversionNotSupportedException) { - HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; - return handleConversionNotSupported((ConversionNotSupportedException) ex, headers, status, request); + if (ex instanceof ConversionNotSupportedException cnse) { + return handleConversionNotSupported(cnse, headers, HttpStatus.INTERNAL_SERVER_ERROR, request); } - else if (ex instanceof TypeMismatchException) { - HttpStatus status = HttpStatus.BAD_REQUEST; - return handleTypeMismatch((TypeMismatchException) ex, headers, status, request); + else if (ex instanceof TypeMismatchException tme) { + return handleTypeMismatch(tme, headers, HttpStatus.BAD_REQUEST, request); } - else if (ex instanceof HttpMessageNotReadableException) { - HttpStatus status = HttpStatus.BAD_REQUEST; - return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, headers, status, request); + else if (ex instanceof HttpMessageNotReadableException hmnre) { + return handleHttpMessageNotReadable(hmnre, headers, HttpStatus.BAD_REQUEST, request); } - else if (ex instanceof HttpMessageNotWritableException) { - HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; - return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, headers, status, request); + else if (ex instanceof HttpMessageNotWritableException hmnwe) { + return handleHttpMessageNotWritable(hmnwe, headers, HttpStatus.INTERNAL_SERVER_ERROR, request); } - else if (ex instanceof BindException) { - HttpStatus status = HttpStatus.BAD_REQUEST; - return handleBindException((BindException) ex, headers, status, request); + else if (ex instanceof BindException be) { + return handleBindException(be, headers, HttpStatus.BAD_REQUEST, request); } else { // Unknown exception, typically a wrapper with a common MVC exception as cause @@ -201,7 +197,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleHttpRequestMethodNotSupported( - HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { pageNotFoundLogger.warn(ex.getMessage()); return handleExceptionInternal(ex, null, headers, status, request); @@ -218,7 +214,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleHttpMediaTypeNotSupported( - HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -234,7 +230,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleHttpMediaTypeNotAcceptable( - HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -251,7 +247,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleMissingPathVariable( - MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + MissingPathVariableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -267,7 +263,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleMissingServletRequestParameter( - MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -283,7 +279,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleMissingServletRequestPart( - MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + MissingServletRequestPartException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -299,7 +295,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleServletRequestBindingException( - ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + ServletRequestBindingException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -315,7 +311,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleMethodArgumentNotValid( - MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -332,7 +328,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleNoHandlerFoundException( - NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + NoHandlerFoundException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -349,7 +345,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleAsyncRequestTimeoutException( - AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest webRequest) { + AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatusCode status, WebRequest webRequest) { return handleExceptionInternal(ex, null, headers, status, webRequest); } @@ -365,7 +361,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleConversionNotSupported( - ConversionNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + ConversionNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -381,7 +377,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleTypeMismatch( - TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + TypeMismatchException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -397,7 +393,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleHttpMessageNotReadable( - HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -413,7 +409,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleHttpMessageNotWritable( - HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -429,7 +425,7 @@ public abstract class ResponseEntityExceptionHandler { */ @Nullable protected ResponseEntity handleBindException( - BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + BindException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); } @@ -442,13 +438,13 @@ public abstract class ResponseEntityExceptionHandler { * @param ex the exception * @param body the body for the response * @param headers the headers for the response - * @param status the response status + * @param statusCode the response status * @param webRequest the current request * @return {@code ResponseEntity} or {@code null} if response is committed */ @Nullable protected ResponseEntity handleExceptionInternal( - Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest webRequest) { + Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest webRequest) { if (webRequest instanceof ServletWebRequest servletWebRequest) { HttpServletResponse response = servletWebRequest.getResponse(); @@ -460,7 +456,7 @@ public abstract class ResponseEntityExceptionHandler { } } - if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { + if (HttpStatus.INTERNAL_SERVER_ERROR.equals(statusCode)) { webRequest.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); } @@ -468,7 +464,7 @@ public abstract class ResponseEntityExceptionHandler { body = errorResponse.getBody(); } - return new ResponseEntity<>(body, headers, status); + return new ResponseEntity<>(body, headers, statusCode); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java index db5d7556cc..eca685048d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java @@ -30,7 +30,7 @@ import org.springframework.core.KotlinDetector; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -147,7 +147,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { * Set the response status according to the {@link ResponseStatus} annotation. */ private void setResponseStatus(ServletWebRequest webRequest) throws IOException { - HttpStatus status = getResponseStatus(); + HttpStatusCode status = getResponseStatus(); if (status == null) { return; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/StreamingResponseBodyReturnValueHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/StreamingResponseBodyReturnValueHandler.java index 4cecd34e8a..230aa99d10 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/StreamingResponseBodyReturnValueHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/StreamingResponseBodyReturnValueHandler.java @@ -71,9 +71,8 @@ public class StreamingResponseBodyReturnValueHandler implements HandlerMethodRet Assert.state(response != null, "No HttpServletResponse"); ServerHttpResponse outputMessage = new ServletServerHttpResponse(response); - if (returnValue instanceof ResponseEntity) { - ResponseEntity responseEntity = (ResponseEntity) returnValue; - response.setStatus(responseEntity.getStatusCodeValue()); + if (returnValue instanceof ResponseEntity responseEntity) { + response.setStatus(responseEntity.getStatusCode().value()); outputMessage.getHeaders().putAll(responseEntity.getHeaders()); returnValue = responseEntity.getBody(); if (returnValue == null) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java index aa106fa068..364a2b064c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java @@ -460,7 +460,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes HttpHeaders headers = errorResponse.getHeaders(); headers.forEach((name, values) -> values.forEach(value -> response.addHeader(name, value))); - int status = errorResponse.getRawStatusCode(); + int status = errorResponse.getStatusCode().value(); String message = errorResponse.getBody().getDetail(); if (message != null) { response.sendError(status, message); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java index a88401e65a..9d0cba4849 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -32,6 +32,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.BeanUtils; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; @@ -98,7 +99,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { private String encodingScheme; @Nullable - private HttpStatus statusCode; + private HttpStatusCode statusCode; private boolean expandUriTemplateVariables = true; @@ -222,7 +223,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { *

Default is to send 302/303, depending on the value of the * {@link #setHttp10Compatible(boolean) http10Compatible} flag. */ - public void setStatusCode(HttpStatus statusCode) { + public void setStatusCode(HttpStatusCode statusCode) { this.statusCode = statusCode; } @@ -613,7 +614,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { String encodedURL = (isRemoteHost(targetUrl) ? targetUrl : response.encodeRedirectURL(targetUrl)); if (http10Compatible) { - HttpStatus attributeStatusCode = (HttpStatus) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE); + HttpStatusCode attributeStatusCode = (HttpStatusCode) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE); if (this.statusCode != null) { response.setStatus(this.statusCode.value()); response.setHeader("Location", encodedURL); @@ -628,7 +629,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { } } else { - HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl); + HttpStatusCode statusCode = getHttp11StatusCode(request, response, targetUrl); response.setStatus(statusCode.value()); response.setHeader("Location", encodedURL); } @@ -662,7 +663,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { /** * Determines the status code to use for HTTP 1.1 compatible requests. - *

The default implementation returns the {@link #setStatusCode(HttpStatus) statusCode} + *

The default implementation returns the {@link #setStatusCode(HttpStatusCode) statusCode} * property if set, or the value of the {@link #RESPONSE_STATUS_ATTRIBUTE} attribute. * If neither are set, it defaults to {@link HttpStatus#SEE_OTHER} (303). * @param request the request to inspect @@ -670,13 +671,13 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { * @param targetUrl the target URL * @return the response status */ - protected HttpStatus getHttp11StatusCode( + protected HttpStatusCode getHttp11StatusCode( HttpServletRequest request, HttpServletResponse response, String targetUrl) { if (this.statusCode != null) { return this.statusCode; } - HttpStatus attributeStatusCode = (HttpStatus) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE); + HttpStatusCode attributeStatusCode = (HttpStatusCode) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE); if (attributeStatusCode != null) { return attributeStatusCode; } diff --git a/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt b/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt index 88381315df..391e824cb2 100644 --- a/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt +++ b/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt @@ -18,7 +18,7 @@ package org.springframework.web.servlet.function import org.springframework.core.io.Resource import org.springframework.http.HttpMethod -import org.springframework.http.HttpStatus +import org.springframework.http.HttpStatusCode import org.springframework.http.MediaType import java.net.URI import java.util.* @@ -767,7 +767,7 @@ class RouterFunctionDsl internal constructor (private val init: (RouterFunctionD /** * @see ServerResponse.status */ - fun status(status: HttpStatus) = ServerResponse.status(status) + fun status(status: HttpStatusCode) = ServerResponse.status(status) /** * @see ServerResponse.status diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java index 13f81baba9..d535e00ee6 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.web.servlet.handler.PathPatternsTestUtils; @@ -53,7 +54,7 @@ class RouterFunctionBuilderTests { ServerRequest getFooRequest = initRequest("GET", "/foo"); - Optional responseStatus = route.route(getFooRequest) + Optional responseStatus = route.route(getFooRequest) .map(handlerFunction -> handle(handlerFunction, getFooRequest)) .map(ServerResponse::statusCode); assertThat(responseStatus).contains(HttpStatus.OK); @@ -102,7 +103,7 @@ class RouterFunctionBuilderTests { ServerRequest resourceRequest = initRequest("GET", "/resources/response.txt"); - Optional responseStatus = route.route(resourceRequest) + Optional responseStatus = route.route(resourceRequest) .map(handlerFunction -> handle(handlerFunction, resourceRequest)) .map(ServerResponse::statusCode); assertThat(responseStatus).contains(HttpStatus.OK); @@ -127,7 +128,7 @@ class RouterFunctionBuilderTests { ServerRequest fooRequest = initRequest("GET", "/foo/bar/baz"); - Optional responseStatus = route.route(fooRequest) + Optional responseStatus = route.route(fooRequest) .map(handlerFunction -> handle(handlerFunction, fooRequest)) .map(ServerResponse::statusCode); assertThat(responseStatus).contains(HttpStatus.OK); @@ -175,7 +176,7 @@ class RouterFunctionBuilderTests { ServerRequest barRequest = initRequest("GET", "/bar"); - Optional responseStatus = route.route(barRequest) + Optional responseStatus = route.route(barRequest) .map(handlerFunction -> handle(handlerFunction, barRequest)) .map(ServerResponse::statusCode); assertThat(responseStatus).contains(HttpStatus.INTERNAL_SERVER_ERROR); @@ -194,7 +195,7 @@ class RouterFunctionBuilderTests { MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/error"); ServerRequest serverRequest = new DefaultServerRequest(servletRequest, emptyList()); - Optional responseStatus = route.route(serverRequest) + Optional responseStatus = route.route(serverRequest) .map(handlerFunction -> handle(handlerFunction, serverRequest)) .map(ServerResponse::statusCode); assertThat(responseStatus).contains(HttpStatus.OK); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java index fad1bab7b6..7805336c98 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java @@ -31,6 +31,7 @@ import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -330,7 +331,7 @@ public class ResponseEntityExceptionHandlerTests { @Override protected ResponseEntity handleServletRequestBindingException( - ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + ServletRequestBindingException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { headers = new HttpHeaders(); headers.set("someHeader", "someHeaderValue"); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/JettyXhrTransport.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/JettyXhrTransport.java index df046d197e..0f00aa0103 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/JettyXhrTransport.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/JettyXhrTransport.java @@ -31,7 +31,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.springframework.context.Lifecycle; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -151,7 +151,7 @@ public class JettyXhrTransport extends AbstractXhrTransport implements Lifecycle catch (Exception ex) { throw new SockJsTransportFailureException("Failed to execute request to " + url, ex); } - HttpStatus status = HttpStatus.valueOf(response.getStatus()); + HttpStatusCode status = HttpStatusCode.valueOf(response.getStatus()); HttpHeaders responseHeaders = toHttpHeaders(response.getHeaders()); return (response.getContent() != null ? new ResponseEntity<>(response.getContentAsString(), responseHeaders, status) : @@ -213,7 +213,7 @@ public class JettyXhrTransport extends AbstractXhrTransport implements Lifecycle @Override public void onBegin(Response response) { if (response.getStatus() != 200) { - HttpStatus status = HttpStatus.valueOf(response.getStatus()); + HttpStatusCode status = HttpStatusCode.valueOf(response.getStatus()); response.abort(new HttpServerErrorException(status, "Unexpected XHR receive status")); } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransport.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransport.java index 41afb4f671..a8fb279b17 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransport.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransport.java @@ -26,6 +26,7 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.http.StreamingHttpOutputMessage; import org.springframework.http.client.ClientHttpRequest; @@ -39,7 +40,6 @@ import org.springframework.web.client.RequestCallback; import org.springframework.web.client.ResponseExtractor; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; -import org.springframework.web.client.UnknownHttpStatusCodeException; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; @@ -156,7 +156,7 @@ public class RestTemplateXhrTransport extends AbstractXhrTransport { private static final ResponseExtractor> textResponseExtractor = response -> { String body = StreamUtils.copyToString(response.getBody(), SockJsFrame.CHARSET); - return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(body); + return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(body); }; @@ -208,11 +208,7 @@ public class RestTemplateXhrTransport extends AbstractXhrTransport { @Override public Object extractData(ClientHttpResponse response) throws IOException { - HttpStatus httpStatus = HttpStatus.resolve(response.getRawStatusCode()); - if (httpStatus == null) { - throw new UnknownHttpStatusCodeException( - response.getRawStatusCode(), response.getStatusText(), response.getHeaders(), null, null); - } + HttpStatusCode httpStatus = response.getStatusCode(); if (httpStatus != HttpStatus.OK) { throw new HttpServerErrorException( httpStatus, response.getStatusText(), response.getHeaders(), null, null); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/UndertowXhrTransport.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/UndertowXhrTransport.java index 1e12b914a6..161d99fe96 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/UndertowXhrTransport.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/UndertowXhrTransport.java @@ -49,7 +49,7 @@ import org.xnio.channels.StreamSinkChannel; import org.xnio.channels.StreamSourceChannel; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -190,7 +190,7 @@ public class UndertowXhrTransport extends AbstractXhrTransport { public void completed(ClientExchange result) { ClientResponse response = result.getResponse(); if (response.getResponseCode() != 200) { - HttpStatus status = HttpStatus.valueOf(response.getResponseCode()); + HttpStatusCode status = HttpStatusCode.valueOf(response.getResponseCode()); IoUtils.safeClose(result.getConnection()); onFailure(new HttpServerErrorException(status, "Unexpected XHR receive status")); } @@ -286,7 +286,7 @@ public class UndertowXhrTransport extends AbstractXhrTransport { latch.await(); ClientResponse response = responses.iterator().next(); - HttpStatus status = HttpStatus.valueOf(response.getResponseCode()); + HttpStatusCode status = HttpStatusCode.valueOf(response.getResponseCode()); HttpHeaders responseHeaders = toHttpHeaders(response.getResponseHeaders()); String responseBody = response.getAttachment(RESPONSE_BODY); return (responseBody != null ? diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java index 18224e3184..d456a72a5d 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java @@ -33,6 +33,7 @@ import org.springframework.context.Lifecycle; import org.springframework.core.log.LogFormatUtils; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpResponse; @@ -316,9 +317,9 @@ public class TransportHandlingSockJsService extends AbstractSockJsService implem transportHandler.handleRequest(request, response, handler, session); - if (isNewSession && (response instanceof ServletServerHttpResponse)) { - int status = ((ServletServerHttpResponse) response).getServletResponse().getStatus(); - if (HttpStatus.valueOf(status).is4xxClientError()) { + if (isNewSession && response instanceof ServletServerHttpResponse servletResponse) { + int status = servletResponse.getServletResponse().getStatus(); + if (HttpStatusCode.valueOf(status).is4xxClientError()) { this.sessions.remove(sessionId); } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/AbstractHttpReceivingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/AbstractHttpReceivingTransportHandler.java index 1e3e933dac..9841c19bd4 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/AbstractHttpReceivingTransportHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/AbstractHttpReceivingTransportHandler.java @@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; @@ -104,6 +105,6 @@ public abstract class AbstractHttpReceivingTransportHandler extends AbstractTran @Nullable protected abstract String[] readMessages(ServerHttpRequest request) throws IOException; - protected abstract HttpStatus getResponseStatus(); + protected abstract HttpStatusCode getResponseStatus(); } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/XhrReceivingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/XhrReceivingTransportHandler.java index 0243f94acf..892708ba06 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/XhrReceivingTransportHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/XhrReceivingTransportHandler.java @@ -19,6 +19,7 @@ package org.springframework.web.socket.sockjs.transport.handler; import java.io.IOException; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.server.ServerHttpRequest; import org.springframework.lang.Nullable; import org.springframework.web.socket.sockjs.transport.TransportHandler; @@ -44,7 +45,7 @@ public class XhrReceivingTransportHandler extends AbstractHttpReceivingTransport } @Override - protected HttpStatus getResponseStatus() { + protected HttpStatusCode getResponseStatus() { return HttpStatus.NO_CONTENT; } diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransportTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransportTests.java index dee39ee3db..f41b56ca96 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransportTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/RestTemplateXhrTransportTests.java @@ -190,7 +190,7 @@ public class RestTemplateXhrTransportTests { private ClientHttpResponse response(HttpStatus status, String body) throws IOException { ClientHttpResponse response = mock(ClientHttpResponse.class); InputStream inputStream = getInputStream(body); - given(response.getRawStatusCode()).willReturn(status.value()); + given(response.getStatusCode()).willReturn(status); given(response.getBody()).willReturn(inputStream); return response; }