Revert errorhandler order in RouterFunctionBuilder
Prior to this commit, error handlers in the WebMvc.fn and WebFlux.fn router function builders had to be registered in an unintuitive, reverse order, due to the filter chain composition model used. This commit reverses the error handler order, so that more specific error handlers can come before generic ones. Closes gh-25541
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.servlet.function;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
@@ -52,36 +53,32 @@ class RouterFunctionBuilderTests {
|
||||
|
||||
ServerRequest getFooRequest = initRequest("GET", "/foo");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(getFooRequest)
|
||||
Optional<HttpStatus> responseStatus = route.route(getFooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, getFooRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(200);
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.OK);
|
||||
|
||||
ServerRequest headFooRequest = initRequest("HEAD", "/foo");
|
||||
|
||||
responseStatus = route.route(headFooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, getFooRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(202);
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.ACCEPTED);
|
||||
|
||||
ServerRequest barRequest = initRequest("POST", "/", req -> req.setContentType("text/plain"));
|
||||
|
||||
responseStatus = route.route(barRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, barRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(204);
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.NO_CONTENT);
|
||||
|
||||
ServerRequest invalidRequest = initRequest("POST", "/");
|
||||
|
||||
responseStatus = route.route(invalidRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, invalidRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
.map(ServerResponse::statusCode);
|
||||
|
||||
assertThat(responseStatus.isPresent()).isFalse();
|
||||
assertThat(responseStatus).isEmpty();
|
||||
}
|
||||
|
||||
private static ServerResponse handle(HandlerFunction<ServerResponse> handlerFunction,
|
||||
@@ -105,19 +102,17 @@ class RouterFunctionBuilderTests {
|
||||
|
||||
ServerRequest resourceRequest = initRequest("GET", "/resources/response.txt");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(resourceRequest)
|
||||
Optional<HttpStatus> responseStatus = route.route(resourceRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, resourceRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(200);
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.OK);
|
||||
|
||||
ServerRequest invalidRequest = initRequest("POST", "/resources/foo.txt");
|
||||
|
||||
responseStatus = route.route(invalidRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, invalidRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.isPresent()).isFalse();
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -132,11 +127,10 @@ class RouterFunctionBuilderTests {
|
||||
|
||||
ServerRequest fooRequest = initRequest("GET", "/foo/bar/baz");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(fooRequest)
|
||||
Optional<HttpStatus> responseStatus = route.route(fooRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, fooRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(200);
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,13 +175,33 @@ class RouterFunctionBuilderTests {
|
||||
|
||||
ServerRequest barRequest = initRequest("GET", "/bar");
|
||||
|
||||
Optional<Integer> responseStatus = route.route(barRequest)
|
||||
Optional<HttpStatus> responseStatus = route.route(barRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, barRequest))
|
||||
.map(ServerResponse::statusCode)
|
||||
.map(HttpStatus::value);
|
||||
assertThat(responseStatus.get().intValue()).isEqualTo(500);
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleOnErrors() {
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||
.GET("/error", request -> {
|
||||
throw new IOException();
|
||||
})
|
||||
.onError(IOException.class, (t, r) -> ServerResponse.status(200).build())
|
||||
.onError(Exception.class, (t, r) -> ServerResponse.status(201).build())
|
||||
.build();
|
||||
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/error");
|
||||
ServerRequest serverRequest = new DefaultServerRequest(servletRequest, emptyList());
|
||||
|
||||
Optional<HttpStatus> responseStatus = route.route(serverRequest)
|
||||
.map(handlerFunction -> handle(handlerFunction, serverRequest))
|
||||
.map(ServerResponse::statusCode);
|
||||
assertThat(responseStatus).contains(HttpStatus.OK);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ServerRequest initRequest(String httpMethod, String requestUri) {
|
||||
return initRequest(httpMethod, requestUri, null);
|
||||
|
||||
Reference in New Issue
Block a user