Improve RouterFunction builder
This commit improves the RouterFunctions.Builder based on conversations had during the weekly team meeting. Issue: SPR-16953
This commit is contained in:
parent
22ccdb285f
commit
91e96d8084
|
|
@ -26,7 +26,7 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,89 +40,111 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||||
|
|
||||||
private List<HandlerFilterFunction<ServerResponse, ServerResponse>> filterFunctions = new ArrayList<>();
|
private List<HandlerFilterFunction<ServerResponse, ServerResponse>> filterFunctions = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder route(RequestPredicate predicate,
|
public RouterFunctions.Builder add(RouterFunction<ServerResponse> routerFunction) {
|
||||||
|
Assert.notNull(routerFunction, "RouterFunction must not be null");
|
||||||
|
this.routerFunctions.add(routerFunction);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RouterFunctions.Builder add(RequestPredicate predicate,
|
||||||
HandlerFunction<ServerResponse> handlerFunction) {
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
this.routerFunctions.add(RouterFunctions.route(predicate, handlerFunction));
|
this.routerFunctions.add(RouterFunctions.route(predicate, handlerFunction));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeGet(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder GET(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.GET), handlerFunction);
|
return add(RequestPredicates.GET(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeGet(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder GET(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.GET(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.GET(pattern).and(predicate), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeHead(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder HEAD(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.HEAD), handlerFunction);
|
return add(RequestPredicates.HEAD(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeHead(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder HEAD(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.HEAD(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.HEAD(pattern).and(predicate), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routePost(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder POST(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.POST), handlerFunction);
|
return add(RequestPredicates.POST(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routePost(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder POST(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.POST(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.POST(pattern).and(predicate), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routePut(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder PUT(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.PUT), handlerFunction);
|
return add(RequestPredicates.PUT(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routePut(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder PUT(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.PUT(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.PUT(pattern).and(predicate), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routePatch(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder PATCH(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.PATCH), handlerFunction);
|
return add(RequestPredicates.PATCH(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routePatch(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder PATCH(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.PATCH(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.PATCH(pattern).and(predicate), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeDelete(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder DELETE(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.DELETE), handlerFunction);
|
return add(RequestPredicates.DELETE(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeDelete(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder DELETE(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.DELETE(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.DELETE(pattern).and(predicate), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeOptions(HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder OPTIONS(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
return route(RequestPredicates.method(HttpMethod.OPTIONS), handlerFunction);
|
return add(RequestPredicates.OPTIONS(pattern), handlerFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder routeOptions(String pattern, HandlerFunction<ServerResponse> handlerFunction) {
|
public RouterFunctions.Builder OPTIONS(String pattern, RequestPredicate predicate,
|
||||||
return route(RequestPredicates.OPTIONS(pattern), handlerFunction);
|
HandlerFunction<ServerResponse> handlerFunction) {
|
||||||
|
return add(RequestPredicates.OPTIONS(pattern).and(predicate), handlerFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RouterFunctions.Builder resources(String pattern, Resource location) {
|
||||||
|
return add(RouterFunctions.resources(pattern, location));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RouterFunctions.Builder resources(Function<ServerRequest, Mono<Resource>> lookupFunction) {
|
||||||
|
return add(RouterFunctions.resources(lookupFunction));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder nest(RequestPredicate predicate,
|
public RouterFunctions.Builder nest(RequestPredicate predicate,
|
||||||
Consumer<RouterFunctions.Builder> builderConsumer) {
|
Consumer<RouterFunctions.Builder> builderConsumer) {
|
||||||
|
|
||||||
Assert.notNull(builderConsumer, "'builderConsumer' must not be null");
|
Assert.notNull(builderConsumer, "Consumer must not be null");
|
||||||
|
|
||||||
RouterFunctionBuilder nestedBuilder = new RouterFunctionBuilder();
|
RouterFunctionBuilder nestedBuilder = new RouterFunctionBuilder();
|
||||||
builderConsumer.accept(nestedBuilder);
|
builderConsumer.accept(nestedBuilder);
|
||||||
|
|
@ -136,7 +158,7 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||||
public RouterFunctions.Builder nest(RequestPredicate predicate,
|
public RouterFunctions.Builder nest(RequestPredicate predicate,
|
||||||
Supplier<RouterFunction<ServerResponse>> routerFunctionSupplier) {
|
Supplier<RouterFunction<ServerResponse>> routerFunctionSupplier) {
|
||||||
|
|
||||||
Assert.notNull(routerFunctionSupplier, "'routerFunctionSupplier' must not be null");
|
Assert.notNull(routerFunctionSupplier, "RouterFunction Supplier must not be null");
|
||||||
|
|
||||||
RouterFunction<ServerResponse> nestedRoute = routerFunctionSupplier.get();
|
RouterFunction<ServerResponse> nestedRoute = routerFunctionSupplier.get();
|
||||||
|
|
||||||
|
|
@ -145,57 +167,56 @@ class RouterFunctionBuilder implements RouterFunctions.Builder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder nestPath(String pattern,
|
public RouterFunctions.Builder path(String pattern,
|
||||||
Consumer<RouterFunctions.Builder> builderConsumer) {
|
Consumer<RouterFunctions.Builder> builderConsumer) {
|
||||||
return nest(RequestPredicates.path(pattern), builderConsumer);
|
return nest(RequestPredicates.path(pattern), builderConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder nestPath(String pattern,
|
public RouterFunctions.Builder path(String pattern,
|
||||||
Supplier<RouterFunction<ServerResponse>> routerFunctionSupplier) {
|
Supplier<RouterFunction<ServerResponse>> routerFunctionSupplier) {
|
||||||
return nest(RequestPredicates.path(pattern), routerFunctionSupplier);
|
return nest(RequestPredicates.path(pattern), routerFunctionSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder filter(HandlerFilterFunction<ServerResponse, ServerResponse> filterFunction) {
|
public RouterFunctions.Builder filter(HandlerFilterFunction<ServerResponse, ServerResponse> filterFunction) {
|
||||||
Assert.notNull(filterFunction, "'filterFunction' must not be null");
|
Assert.notNull(filterFunction, "HandlerFilterFunction must not be null");
|
||||||
|
|
||||||
this.filterFunctions.add(filterFunction);
|
this.filterFunctions.add(filterFunction);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder filterBefore(
|
public RouterFunctions.Builder before(Function<ServerRequest, ServerRequest> requestProcessor) {
|
||||||
Function<ServerRequest, Mono<ServerRequest>> requestProcessor) {
|
Assert.notNull(requestProcessor, "RequestProcessor must not be null");
|
||||||
|
return filter((request, next) -> next.handle(requestProcessor.apply(request)));
|
||||||
Assert.notNull(requestProcessor, "Function must not be null");
|
|
||||||
return filter((request, next) -> requestProcessor.apply(request).flatMap(next::handle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder filterAfter(
|
public RouterFunctions.Builder after(
|
||||||
BiFunction<ServerRequest, ServerResponse, Mono<ServerResponse>> responseProcessor) {
|
BiFunction<ServerRequest, ServerResponse, ServerResponse> responseProcessor) {
|
||||||
|
Assert.notNull(responseProcessor, "ResponseProcessor must not be null");
|
||||||
return filter((request, next) -> next.handle(request)
|
return filter((request, next) -> next.handle(request)
|
||||||
.flatMap(serverResponse -> responseProcessor.apply(request, serverResponse)));
|
.map(serverResponse -> responseProcessor.apply(request, serverResponse)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunctions.Builder filterException(Predicate<? super Throwable> predicate,
|
public RouterFunctions.Builder onError(Predicate<? super Throwable> predicate,
|
||||||
BiFunction<? super Throwable, ServerRequest, Mono<ServerResponse>> responseProvider) {
|
BiFunction<? super Throwable, ServerRequest, Mono<ServerResponse>> responseProvider) {
|
||||||
|
|
||||||
Assert.notNull(predicate, "'exceptionType' must not be null");
|
Assert.notNull(predicate, "Predicate must not be null");
|
||||||
Assert.notNull(responseProvider, "'fallback' must not be null");
|
Assert.notNull(responseProvider, "ResponseProvider must not be null");
|
||||||
|
|
||||||
return filter((request, next) -> next.handle(request)
|
return filter((request, next) -> next.handle(request)
|
||||||
.onErrorResume(predicate, t -> responseProvider.apply(t, request)));
|
.onErrorResume(predicate, t -> responseProvider.apply(t, request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Throwable> RouterFunctions.Builder filterException(
|
public <T extends Throwable> RouterFunctions.Builder onError(
|
||||||
Class<T> exceptionType,
|
Class<T> exceptionType,
|
||||||
BiFunction<? super T, ServerRequest, Mono<ServerResponse>> responseProvider) {
|
BiFunction<? super T, ServerRequest, Mono<ServerResponse>> responseProvider) {
|
||||||
Assert.notNull(exceptionType, "'exceptionType' must not be null");
|
Assert.notNull(exceptionType, "ExceptionType must not be null");
|
||||||
Assert.notNull(responseProvider, "'fallback' must not be null");
|
Assert.notNull(responseProvider, "ResponseProvider must not be null");
|
||||||
|
|
||||||
return filter((request, next) -> next.handle(request)
|
return filter((request, next) -> next.handle(request)
|
||||||
.onErrorResume(exceptionType, t -> responseProvider.apply(t, request)));
|
.onErrorResume(exceptionType, t -> responseProvider.apply(t, request)));
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||||
/**
|
/**
|
||||||
* <strong>Central entry point to Spring's functional web framework.</strong>
|
* <strong>Central entry point to Spring's functional web framework.</strong>
|
||||||
* Exposes routing functionality, such as to
|
* Exposes routing functionality, such as to
|
||||||
|
* {@linkplain #route() create} a {@code RouterFunction} using a discoverable builder-style API,
|
||||||
|
* to
|
||||||
* {@linkplain #route(RequestPredicate, HandlerFunction) create} a {@code RouterFunction}
|
* {@linkplain #route(RequestPredicate, HandlerFunction) create} a {@code RouterFunction}
|
||||||
* given a {@code RequestPredicate} and {@code HandlerFunction}, and to do further
|
* given a {@code RequestPredicate} and {@code HandlerFunction}, and to do further
|
||||||
* {@linkplain #nest(RequestPredicate, RouterFunction) subrouting} on an existing routing
|
* {@linkplain #nest(RequestPredicate, RouterFunction) subrouting} on an existing routing
|
||||||
|
|
@ -73,11 +75,11 @@ public abstract class RouterFunctions {
|
||||||
private static final HandlerFunction<ServerResponse> NOT_FOUND_HANDLER = request -> ServerResponse.notFound().build();
|
private static final HandlerFunction<ServerResponse> NOT_FOUND_HANDLER = request -> ServerResponse.notFound().build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a {@linkplain Builder builder} that offers a discoverable way to create router
|
* Offers a discoverable way to create router functions through a builder-style interface.
|
||||||
* functions.
|
|
||||||
* @return a router function builder
|
* @return a router function builder
|
||||||
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public static Builder builder() {
|
public static Builder route() {
|
||||||
return new RouterFunctionBuilder();
|
return new RouterFunctionBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,38 +284,12 @@ public abstract class RouterFunctions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a builder for router functions.
|
* Represents a discoverable builder for router functions. Obtained via
|
||||||
* <p>Each invocation of {@code route} creates a new {@link RouterFunction} that is
|
* {@link RouterFunctions#route()}.
|
||||||
* {@linkplain RouterFunction#and(RouterFunction) composed} with any previously built functions.
|
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public interface Builder {
|
public interface Builder {
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a route to the given handler function that matches if the given request predicate
|
|
||||||
* applies.
|
|
||||||
* <p>For instance, the following example routes GET requests for "/user" to the
|
|
||||||
* {@code listUsers} method in {@code userController}:
|
|
||||||
* <pre class="code">
|
|
||||||
* RouterFunction<ServerResponse> route =
|
|
||||||
* RouterFunctions.builder()
|
|
||||||
* .route(RequestPredicates.GET("/user"), userController::listUsers)
|
|
||||||
* .build();
|
|
||||||
* </pre>
|
|
||||||
* @param predicate the predicate to test
|
|
||||||
* @param handlerFunction the handler function to route to if the predicate applies
|
|
||||||
* @return this builder
|
|
||||||
* @see RequestPredicates
|
|
||||||
*/
|
|
||||||
Builder route(RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code GET} requests.
|
|
||||||
* @param handlerFunction the handler function to handle all {@code GET} requests
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
Builder routeGet(HandlerFunction<ServerResponse> handlerFunction);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code GET} requests
|
* Adds a route to the given handler function that handles all HTTP {@code GET} requests
|
||||||
* that match the given pattern.
|
* that match the given pattern.
|
||||||
|
|
@ -322,14 +298,28 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routeGet(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder GET(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code HEAD} requests.
|
* Adds a route to the given handler function that handles all HTTP {@code GET} requests
|
||||||
* @param handlerFunction the handler function to handle all {@code HEAD} requests
|
* that match the given pattern and predicate.
|
||||||
|
* <p>For instance, the following example routes GET requests for "/user" that accept JSON
|
||||||
|
* to the {@code listUsers} method in {@code userController}:
|
||||||
|
* <pre class="code">
|
||||||
|
* RouterFunction<ServerResponse> route =
|
||||||
|
* RouterFunctions.route()
|
||||||
|
* .GET("/user", RequestPredicates.accept(MediaType.APPLICATION_JSON),
|
||||||
|
* userController::listUsers)
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code GET} requests that
|
||||||
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
|
* @see RequestPredicates
|
||||||
*/
|
*/
|
||||||
Builder routeHead(HandlerFunction<ServerResponse> handlerFunction);
|
Builder GET(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code HEAD} requests
|
* Adds a route to the given handler function that handles all HTTP {@code HEAD} requests
|
||||||
|
|
@ -339,14 +329,18 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routeHead(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder HEAD(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code POST} requests.
|
* Adds a route to the given handler function that handles all HTTP {@code HEAD} requests
|
||||||
* @param handlerFunction the handler function to handle all {@code POST} requests
|
* that match the given pattern and predicate.
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code HEAD} requests that
|
||||||
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routePost(HandlerFunction<ServerResponse> handlerFunction);
|
Builder HEAD(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code POST} requests
|
* Adds a route to the given handler function that handles all HTTP {@code POST} requests
|
||||||
|
|
@ -356,14 +350,27 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routePost(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder POST(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code PUT} requests.
|
* Adds a route to the given handler function that handles all HTTP {@code POST} requests
|
||||||
* @param handlerFunction the handler function to handle all {@code PUT} requests
|
* that match the given pattern and predicate.
|
||||||
|
* <p>For instance, the following example routes POST requests for "/user" that contain JSON
|
||||||
|
* to the {@code addUser} method in {@code userController}:
|
||||||
|
* <pre class="code">
|
||||||
|
* RouterFunction<ServerResponse> route =
|
||||||
|
* RouterFunctions.route()
|
||||||
|
* .POST("/user", RequestPredicates.contentType(MediaType.APPLICATION_JSON),
|
||||||
|
* userController::addUser)
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code POST} requests that
|
||||||
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routePut(HandlerFunction<ServerResponse> handlerFunction);
|
Builder POST(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code PUT} requests
|
* Adds a route to the given handler function that handles all HTTP {@code PUT} requests
|
||||||
|
|
@ -373,14 +380,27 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routePut(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder PUT(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code PATCH} requests.
|
* Adds a route to the given handler function that handles all HTTP {@code PUT} requests
|
||||||
* @param handlerFunction the handler function to handle all {@code PATCH} requests
|
* that match the given pattern and predicate.
|
||||||
|
* <p>For instance, the following example routes PUT requests for "/user" that contain JSON
|
||||||
|
* to the {@code editUser} method in {@code userController}:
|
||||||
|
* <pre class="code">
|
||||||
|
* RouterFunction<ServerResponse> route =
|
||||||
|
* RouterFunctions.route()
|
||||||
|
* .PUT("/user", RequestPredicates.contentType(MediaType.APPLICATION_JSON),
|
||||||
|
* userController::editUser)
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code PUT} requests that
|
||||||
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routePatch(HandlerFunction<ServerResponse> handlerFunction);
|
Builder PUT(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code PATCH} requests
|
* Adds a route to the given handler function that handles all HTTP {@code PATCH} requests
|
||||||
|
|
@ -390,14 +410,27 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routePatch(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder PATCH(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code DELETE} requests.
|
* Adds a route to the given handler function that handles all HTTP {@code PATCH} requests
|
||||||
* @param handlerFunction the handler function to handle all {@code DELETE} requests
|
* that match the given pattern and predicate.
|
||||||
|
* <p>For instance, the following example routes PATCH requests for "/user" that contain JSON
|
||||||
|
* to the {@code editUser} method in {@code userController}:
|
||||||
|
* <pre class="code">
|
||||||
|
* RouterFunction<ServerResponse> route =
|
||||||
|
* RouterFunctions.route()
|
||||||
|
* .PATCH("/user", RequestPredicates.contentType(MediaType.APPLICATION_JSON),
|
||||||
|
* userController::editUser)
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code PATCH} requests that
|
||||||
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routeDelete(HandlerFunction<ServerResponse> handlerFunction);
|
Builder PATCH(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code DELETE} requests
|
* Adds a route to the given handler function that handles all HTTP {@code DELETE} requests
|
||||||
|
|
@ -407,14 +440,18 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routeDelete(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder DELETE(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code OPTIONS} requests.
|
* Adds a route to the given handler function that handles all HTTP {@code DELETE} requests
|
||||||
* @param handlerFunction the handler function to handle all {@code OPTIONS} requests
|
* that match the given pattern and predicate.
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code DELETE} requests that
|
||||||
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routeOptions(HandlerFunction<ServerResponse> handlerFunction);
|
Builder DELETE(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a route to the given handler function that handles all HTTP {@code OPTIONS} requests
|
* Adds a route to the given handler function that handles all HTTP {@code OPTIONS} requests
|
||||||
|
|
@ -424,7 +461,61 @@ public abstract class RouterFunctions {
|
||||||
* match {@code pattern}
|
* match {@code pattern}
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder routeOptions(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
Builder OPTIONS(String pattern, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a route to the given handler function that handles all HTTP {@code OPTIONS} requests
|
||||||
|
* that match the given pattern and predicate.
|
||||||
|
* @param pattern the pattern to match to
|
||||||
|
* @param predicate additional predicate to match
|
||||||
|
* @param handlerFunction the handler function to handle all {@code OPTIONS} requests that
|
||||||
|
* match {@code pattern}
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
Builder OPTIONS(String pattern, RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given route to this builder. Can be used to merge externally defined router
|
||||||
|
* functions into this builder, or can be combined with
|
||||||
|
* {@link RouterFunctions#route(RequestPredicate, HandlerFunction)}
|
||||||
|
* to allow for more flexible predicate matching.
|
||||||
|
* <p>For instance, the following example adds the router function returned from
|
||||||
|
* {@code OrderController.routerFunction()}.
|
||||||
|
* to the {@code changeUser} method in {@code userController}:
|
||||||
|
* <pre class="code">
|
||||||
|
* RouterFunction<ServerResponse> route =
|
||||||
|
* RouterFunctions.route()
|
||||||
|
* .GET("/users", userController::listUsers)
|
||||||
|
* .add(orderController.routerFunction());
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
* @param routerFunction the router function to be added
|
||||||
|
* @return this builder
|
||||||
|
* @see RequestPredicates
|
||||||
|
*/
|
||||||
|
Builder add(RouterFunction<ServerResponse> routerFunction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route requests that match the given pattern to resources relative to the given root location.
|
||||||
|
* For instance
|
||||||
|
* <pre class="code">
|
||||||
|
* Resource location = new FileSystemResource("public-resources/");
|
||||||
|
* RouterFunction<ServerResponse> resources = RouterFunctions.resources("/resources/**", location);
|
||||||
|
* </pre>
|
||||||
|
* @param pattern the pattern to match
|
||||||
|
* @param location the location directory relative to which resources should be resolved
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
Builder resources(String pattern, Resource location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route to resources using the provided lookup function. If the lookup function provides a
|
||||||
|
* {@link Resource} for the given request, it will be it will be exposed using a
|
||||||
|
* {@link HandlerFunction} that handles GET, HEAD, and OPTIONS requests.
|
||||||
|
* @param lookupFunction the function to provide a {@link Resource} given the {@link ServerRequest}
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
Builder resources(Function<ServerRequest, Mono<Resource>> lookupFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route to the supplied router function if the given request predicate applies. This method
|
* Route to the supplied router function if the given request predicate applies. This method
|
||||||
|
|
@ -435,11 +526,11 @@ public abstract class RouterFunctions {
|
||||||
* and POST request for "/user" will create a new user.
|
* and POST request for "/user" will create a new user.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> nestedRoute =
|
* RouterFunction<ServerResponse> nestedRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .nest(RequestPredicates.path("/user"), () ->
|
* .nest(RequestPredicates.path("/user"), () ->
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .routeGet(this::listUsers)
|
* .GET(this::listUsers)
|
||||||
* .routePost(this::createUser);
|
* .POST(this::createUser);
|
||||||
* .build();
|
* .build();
|
||||||
* )
|
* )
|
||||||
* .build();
|
* .build();
|
||||||
|
|
@ -461,10 +552,10 @@ public abstract class RouterFunctions {
|
||||||
* and POST request for "/user" will create a new user.
|
* and POST request for "/user" will create a new user.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> nestedRoute =
|
* RouterFunction<ServerResponse> nestedRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .nest(RequestPredicates.path("/user"), builder ->
|
* .nest(RequestPredicates.path("/user"), builder ->
|
||||||
* builder.routeGet(this::listUsers)
|
* builder.GET(this::listUsers)
|
||||||
* .routePost(this::createUser);
|
* .POST(this::createUser);
|
||||||
* )
|
* )
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
|
@ -479,19 +570,16 @@ public abstract class RouterFunctions {
|
||||||
/**
|
/**
|
||||||
* Route to the supplied router function if the given path prefix pattern applies. This method
|
* Route to the supplied router function if the given path prefix pattern applies. This method
|
||||||
* can be used to create <strong>nested routes</strong>, where a group of routes share a
|
* can be used to create <strong>nested routes</strong>, where a group of routes share a
|
||||||
* common path (prefix).
|
* common path prefix. Specifically, this method can be used to merge externally defined
|
||||||
|
* router functions under a path prefix.
|
||||||
* <p>For instance, the following example creates a nested route with a "/user" path
|
* <p>For instance, the following example creates a nested route with a "/user" path
|
||||||
* predicate, so that GET requests for "/user" will list users,
|
* predicate that delegates to the router function defined in {@code userController},
|
||||||
* and POST request for "/user" will create a new user.
|
* and with a "/order" path that delegates to {@code orderController}.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> nestedRoute =
|
* RouterFunction<ServerResponse> nestedRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .nestPath("/user", () ->
|
* .path("/user", userController::routerFunction)
|
||||||
* RouterFunctions.builder()
|
* .path("/order", orderController::routerFunction)
|
||||||
* .routeGet(this::listUsers)
|
|
||||||
* .routePost(this::createUser);
|
|
||||||
* .build();
|
|
||||||
* )
|
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
* @param pattern the pattern to match to
|
* @param pattern the pattern to match to
|
||||||
|
|
@ -499,21 +587,21 @@ public abstract class RouterFunctions {
|
||||||
* the pattern matches
|
* the pattern matches
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder nestPath(String pattern, Supplier<RouterFunction<ServerResponse>> routerFunctionSupplier);
|
Builder path(String pattern, Supplier<RouterFunction<ServerResponse>> routerFunctionSupplier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route to a built router function if the given path prefix pattern applies.
|
* Route to a built router function if the given path prefix pattern applies.
|
||||||
* This method can be used to create <strong>nested routes</strong>, where a group of routes
|
* This method can be used to create <strong>nested routes</strong>, where a group of routes
|
||||||
* share a common path (prefix), header, or other request predicate.
|
* share a common path prefix.
|
||||||
* <p>For instance, the following example creates a nested route with a "/user" path
|
* <p>For instance, the following example creates a nested route with a "/user" path
|
||||||
* predicate, so that GET requests for "/user" will list users,
|
* predicate, so that GET requests for "/user" will list users,
|
||||||
* and POST request for "/user" will create a new user.
|
* and POST request for "/user" will create a new user.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> nestedRoute =
|
* RouterFunction<ServerResponse> nestedRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .nestPath("/user", builder ->
|
* .path("/user", builder ->
|
||||||
* builder.routeGet(this::listUsers)
|
* builder.GET(this::listUsers)
|
||||||
* .routePost(this::createUser);
|
* .POST(this::createUser);
|
||||||
* )
|
* )
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
|
@ -522,22 +610,26 @@ public abstract class RouterFunctions {
|
||||||
* function
|
* function
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder nestPath(String pattern, Consumer<Builder> builderConsumer);
|
Builder path(String pattern, Consumer<Builder> builderConsumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters all routes created by this builder with the given filter function. Filter
|
* Filters all routes created by this builder with the given filter function. Filter
|
||||||
* functions are typically used to address cross-cutting concerns, such as logging,
|
* functions are typically used to address cross-cutting concerns, such as logging,
|
||||||
* security, etc.
|
* security, etc.
|
||||||
* <p>For instance, the following example creates a filter that logs the request before
|
* <p>For instance, the following example creates a filter that returns a 401 Unauthorized
|
||||||
* the handler function executes, and logs the response after.
|
* response if the request does not contain the necessary authentication headers.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> filteredRoute =
|
* RouterFunction<ServerResponse> filteredRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .routeGet("/user", this::listUsers)
|
* .GET("/user", this::listUsers)
|
||||||
* .filter((request, next) -> {
|
* .filter((request, next) -> {
|
||||||
* log(request);
|
* // check for authentication headers
|
||||||
* Mono<ServerResponse> responseMono = next.handle(request);
|
* if (isAuthenticated(request)) {
|
||||||
* return responseMono.doOnNext(response -> log(response);
|
* return next.handle(request);
|
||||||
|
* }
|
||||||
|
* else {
|
||||||
|
* return ServerResponse.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
* }
|
||||||
* })
|
* })
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
|
@ -547,46 +639,46 @@ public abstract class RouterFunctions {
|
||||||
Builder filter(HandlerFilterFunction<ServerResponse, ServerResponse> filterFunction);
|
Builder filter(HandlerFilterFunction<ServerResponse, ServerResponse> filterFunction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the request for all routes created by this builder with the given request
|
* Filter the request object for all routes created by this builder with the given request
|
||||||
* processing function. Filters are typically used to address cross-cutting concerns, such
|
* processing function. Filters are typically used to address cross-cutting concerns, such
|
||||||
* as logging, security, etc.
|
* as logging, security, etc.
|
||||||
* <p>For instance, the following example creates a filter that logs the request before
|
* <p>For instance, the following example creates a filter that logs the request before
|
||||||
* the handler function executes.
|
* the handler function executes.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> filteredRoute =
|
* RouterFunction<ServerResponse> filteredRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .routeGet("/user", this::listUsers)
|
* .GET("/user", this::listUsers)
|
||||||
* .filterBefore(request -> {
|
* .before(request -> {
|
||||||
* log(request);
|
* log(request);
|
||||||
* return Mono.just(request);
|
* return request;
|
||||||
* })
|
* })
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
* @param requestProcessor a function that transforms the request
|
* @param requestProcessor a function that transforms the request
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder filterBefore(Function<ServerRequest, Mono<ServerRequest>> requestProcessor);
|
Builder before(Function<ServerRequest, ServerRequest> requestProcessor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the response for all routes created by this builder with the given response
|
* Filter the response object for all routes created by this builder with the given response
|
||||||
* processing function. Filters are typically used to address cross-cutting concerns, such
|
* processing function. Filters are typically used to address cross-cutting concerns, such
|
||||||
* as logging, security, etc.
|
* as logging, security, etc.
|
||||||
* <p>For instance, the following example creates a filter that logs the response after
|
* <p>For instance, the following example creates a filter that logs the response after
|
||||||
* the handler function executes.
|
* the handler function executes.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> filteredRoute =
|
* RouterFunction<ServerResponse> filteredRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .routeGet("/user", this::listUsers)
|
* .GET("/user", this::listUsers)
|
||||||
* .filterAfter((request, response) -> {
|
* .after((request, response) -> {
|
||||||
* log(response);
|
* log(response);
|
||||||
* return Mono.just(response);
|
* return response;
|
||||||
* })
|
* })
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
* @param responseProcessor a function that transforms the response
|
* @param responseProcessor a function that transforms the response
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder filterAfter(BiFunction<ServerRequest, ServerResponse, Mono<ServerResponse>> responseProcessor);
|
Builder after(BiFunction<ServerRequest, ServerResponse, ServerResponse> responseProcessor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters all exceptions that match the predicate by applying the given response provider
|
* Filters all exceptions that match the predicate by applying the given response provider
|
||||||
|
|
@ -595,9 +687,9 @@ public abstract class RouterFunctions {
|
||||||
* status when an {@code IllegalStateException} occurs.
|
* status when an {@code IllegalStateException} occurs.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> filteredRoute =
|
* RouterFunction<ServerResponse> filteredRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .routeGet("/user", this::listUsers)
|
* .GET("/user", this::listUsers)
|
||||||
* .filterException(e -> e instanceof IllegalStateException,
|
* .onError(e -> e instanceof IllegalStateException,
|
||||||
* (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
|
* (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
|
@ -605,7 +697,7 @@ public abstract class RouterFunctions {
|
||||||
* @param responseProvider a function that creates a response
|
* @param responseProvider a function that creates a response
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
Builder filterException(Predicate<? super Throwable> predicate,
|
Builder onError(Predicate<? super Throwable> predicate,
|
||||||
BiFunction<? super Throwable, ServerRequest, Mono<ServerResponse>> responseProvider);
|
BiFunction<? super Throwable, ServerRequest, Mono<ServerResponse>> responseProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -615,9 +707,9 @@ public abstract class RouterFunctions {
|
||||||
* status when an {@code IllegalStateException} occurs.
|
* status when an {@code IllegalStateException} occurs.
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* RouterFunction<ServerResponse> filteredRoute =
|
* RouterFunction<ServerResponse> filteredRoute =
|
||||||
* RouterFunctions.builder()
|
* RouterFunctions.route()
|
||||||
* .routeGet("/user", this::listUsers)
|
* .GET("/user", this::listUsers)
|
||||||
* .filterException(IllegalStateException.class,
|
* .onError(IllegalStateException.class,
|
||||||
* (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
|
* (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
|
@ -625,13 +717,13 @@ public abstract class RouterFunctions {
|
||||||
* @param responseProvider a function that creates a response
|
* @param responseProvider a function that creates a response
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
<T extends Throwable> Builder filterException(Class<T> exceptionType,
|
<T extends Throwable> Builder onError(Class<T> exceptionType,
|
||||||
BiFunction<? super T, ServerRequest, Mono<ServerResponse>> responseProvider);
|
BiFunction<? super T, ServerRequest, Mono<ServerResponse>> responseProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the {@code RouterFunction}. All created routes are
|
* Builds the {@code RouterFunction}. All created routes are
|
||||||
* {@linkplain RouterFunction#and(RouterFunction) composed} with one another, and filters
|
* {@linkplain RouterFunction#and(RouterFunction) composed} with one another, and filters
|
||||||
* (f any) are applied to the result.
|
* (if any) are applied to the result.
|
||||||
* @return the built router function
|
* @return the built router function
|
||||||
*/
|
*/
|
||||||
RouterFunction<ServerResponse> build();
|
RouterFunction<ServerResponse> build();
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,11 @@ import org.junit.Test;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
|
@ -35,10 +38,11 @@ public class RouterFunctionBuilderTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void route() {
|
public void route() {
|
||||||
RouterFunction<ServerResponse> route = RouterFunctions.builder()
|
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||||
.routeGet("/foo", request -> ServerResponse.ok().build())
|
.GET("/foo", request -> ServerResponse.ok().build())
|
||||||
.routePost(request -> ServerResponse.noContent().build())
|
.POST("/", RequestPredicates.contentType(MediaType.TEXT_PLAIN), request -> ServerResponse.noContent().build())
|
||||||
.build();
|
.build();
|
||||||
|
System.out.println(route);
|
||||||
|
|
||||||
MockServerRequest fooRequest = MockServerRequest.builder().
|
MockServerRequest fooRequest = MockServerRequest.builder().
|
||||||
method(HttpMethod.GET).
|
method(HttpMethod.GET).
|
||||||
|
|
@ -56,7 +60,8 @@ public class RouterFunctionBuilderTests {
|
||||||
|
|
||||||
MockServerRequest barRequest = MockServerRequest.builder().
|
MockServerRequest barRequest = MockServerRequest.builder().
|
||||||
method(HttpMethod.POST).
|
method(HttpMethod.POST).
|
||||||
uri(URI.create("http://localhost"))
|
uri(URI.create("http://localhost/"))
|
||||||
|
.header("Content-Type", "text/plain")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
responseMono = route.route(barRequest)
|
responseMono = route.route(barRequest)
|
||||||
|
|
@ -68,15 +73,65 @@ public class RouterFunctionBuilderTests {
|
||||||
.expectNext(204)
|
.expectNext(204)
|
||||||
.verifyComplete();
|
.verifyComplete();
|
||||||
|
|
||||||
|
MockServerRequest invalidRequest = MockServerRequest.builder().
|
||||||
|
method(HttpMethod.POST).
|
||||||
|
uri(URI.create("http://localhost/"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
responseMono = route.route(invalidRequest)
|
||||||
|
.flatMap(handlerFunction -> handlerFunction.handle(invalidRequest))
|
||||||
|
.map(ServerResponse::statusCode)
|
||||||
|
.map(HttpStatus::value);
|
||||||
|
|
||||||
|
StepVerifier.create(responseMono)
|
||||||
|
.verifyComplete();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resources() {
|
||||||
|
Resource resource = new ClassPathResource("/org/springframework/web/reactive/function/server/");
|
||||||
|
assertTrue(resource.exists());
|
||||||
|
|
||||||
|
RouterFunction<ServerResponse> route = RouterFunctions.route()
|
||||||
|
.resources("/resources/**", resource)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
MockServerRequest resourceRequest = MockServerRequest.builder().
|
||||||
|
method(HttpMethod.GET).
|
||||||
|
uri(URI.create("http://localhost/resources/response.txt"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Mono<Integer> responseMono = route.route(resourceRequest)
|
||||||
|
.flatMap(handlerFunction -> handlerFunction.handle(resourceRequest))
|
||||||
|
.map(ServerResponse::statusCode)
|
||||||
|
.map(HttpStatus::value);
|
||||||
|
|
||||||
|
StepVerifier.create(responseMono)
|
||||||
|
.expectNext(200)
|
||||||
|
.verifyComplete();
|
||||||
|
|
||||||
|
MockServerRequest invalidRequest = MockServerRequest.builder().
|
||||||
|
method(HttpMethod.POST).
|
||||||
|
uri(URI.create("http://localhost/resources/foo.txt"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
responseMono = route.route(invalidRequest)
|
||||||
|
.flatMap(handlerFunction -> handlerFunction.handle(invalidRequest))
|
||||||
|
.map(ServerResponse::statusCode)
|
||||||
|
.map(HttpStatus::value);
|
||||||
|
|
||||||
|
StepVerifier.create(responseMono)
|
||||||
|
.verifyComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nest() {
|
public void nest() {
|
||||||
RouterFunction<?> route = RouterFunctions.builder()
|
RouterFunction<?> route = RouterFunctions.route()
|
||||||
.nestPath("/foo", builder ->
|
.path("/foo", builder ->
|
||||||
builder.nestPath("/bar",
|
builder.path("/bar",
|
||||||
() -> RouterFunctions.builder()
|
() -> RouterFunctions.route()
|
||||||
.routeGet("/baz", request -> ServerResponse.ok().build())
|
.GET("/baz", request -> ServerResponse.ok().build())
|
||||||
.build()))
|
.build()))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
@ -99,18 +154,18 @@ public class RouterFunctionBuilderTests {
|
||||||
public void filters() {
|
public void filters() {
|
||||||
AtomicInteger filterCount = new AtomicInteger();
|
AtomicInteger filterCount = new AtomicInteger();
|
||||||
|
|
||||||
RouterFunction<?> route = RouterFunctions.builder()
|
RouterFunction<?> route = RouterFunctions.route()
|
||||||
.routeGet("/foo", request -> ServerResponse.ok().build())
|
.GET("/foo", request -> ServerResponse.ok().build())
|
||||||
.routeGet("/bar", request -> Mono.error(new IllegalStateException()))
|
.GET("/bar", request -> Mono.error(new IllegalStateException()))
|
||||||
.filterBefore(request -> {
|
.before(request -> {
|
||||||
int count = filterCount.getAndIncrement();
|
int count = filterCount.getAndIncrement();
|
||||||
assertEquals(0, count);
|
assertEquals(0, count);
|
||||||
return Mono.just(request);
|
return request;
|
||||||
})
|
})
|
||||||
.filterAfter((request, response) -> {
|
.after((request, response) -> {
|
||||||
int count = filterCount.getAndIncrement();
|
int count = filterCount.getAndIncrement();
|
||||||
assertEquals(3, count);
|
assertEquals(3, count);
|
||||||
return Mono.just(response);
|
return response;
|
||||||
})
|
})
|
||||||
.filter((request, next) -> {
|
.filter((request, next) -> {
|
||||||
int count = filterCount.getAndIncrement();
|
int count = filterCount.getAndIncrement();
|
||||||
|
|
@ -120,7 +175,7 @@ public class RouterFunctionBuilderTests {
|
||||||
assertEquals(2, count);
|
assertEquals(2, count);
|
||||||
return responseMono;
|
return responseMono;
|
||||||
})
|
})
|
||||||
.filterException(IllegalStateException.class, (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
|
.onError(IllegalStateException.class, (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
MockServerRequest fooRequest = MockServerRequest.builder().
|
MockServerRequest fooRequest = MockServerRequest.builder().
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue