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:
@@ -23,6 +23,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -43,6 +44,8 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||
|
||||
private final List<HandlerFilterFunction<ServerResponse, ServerResponse>> filterFunctions = new ArrayList<>();
|
||||
|
||||
private final List<HandlerFilterFunction<ServerResponse, ServerResponse>> errorHandlers = new ArrayList<>();
|
||||
|
||||
|
||||
@Override
|
||||
public RouterFunctions.Builder add(RouterFunction<ServerResponse> routerFunction) {
|
||||
@@ -310,8 +313,9 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||
Assert.notNull(predicate, "Predicate must not be null");
|
||||
Assert.notNull(responseProvider, "ResponseProvider must not be null");
|
||||
|
||||
return filter((request, next) -> next.handle(request)
|
||||
this.errorHandlers.add(0, (request, next) -> next.handle(request)
|
||||
.onErrorResume(predicate, t -> responseProvider.apply(t, request)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -321,8 +325,9 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||
Assert.notNull(exceptionType, "ExceptionType must not be null");
|
||||
Assert.notNull(responseProvider, "ResponseProvider must not be null");
|
||||
|
||||
return filter((request, next) -> next.handle(request)
|
||||
this.errorHandlers.add(0, (request, next) -> next.handle(request)
|
||||
.onErrorResume(exceptionType, t -> responseProvider.apply(t, request)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -332,12 +337,12 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||
}
|
||||
RouterFunction<ServerResponse> result = new BuiltRouterFunction(this.routerFunctions);
|
||||
|
||||
if (this.filterFunctions.isEmpty()) {
|
||||
if (this.filterFunctions.isEmpty() && this.errorHandlers.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
HandlerFilterFunction<ServerResponse, ServerResponse> filter =
|
||||
this.filterFunctions.stream()
|
||||
Stream.concat(this.filterFunctions.stream(), this.errorHandlers.stream())
|
||||
.reduce(HandlerFilterFunction::andThen)
|
||||
.orElseThrow(IllegalStateException::new);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.reactive.function.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -210,4 +211,26 @@ public class RouterFunctionBuilderTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleOnErrors() {
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||
.GET("/error", request -> Mono.error(new IOException()))
|
||||
.onError(IOException.class, (t, r) -> ServerResponse.status(200).build())
|
||||
.onError(Exception.class, (t, r) -> ServerResponse.status(201).build())
|
||||
.build();
|
||||
|
||||
MockServerHttpRequest mockRequest = MockServerHttpRequest.get("https://example.com/error").build();
|
||||
ServerRequest serverRequest = new DefaultServerRequest(MockServerWebExchange.from(mockRequest), Collections.emptyList());
|
||||
|
||||
Mono<HttpStatus> responseStatus = route.route(serverRequest)
|
||||
.flatMap(handlerFunction -> handlerFunction.handle(serverRequest))
|
||||
.map(ServerResponse::statusCode);
|
||||
|
||||
StepVerifier.create(responseStatus)
|
||||
.assertNext(status -> assertThat(status).isEqualTo(HttpStatus.OK))
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user