/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.web.router.filter;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.filter.HttpFilter;
import io.micronaut.web.router.RouteMatch;
import io.micronaut.web.router.Router;
import io.micronaut.web.router.UriRoute;
import io.micronaut.web.router.UriRouteMatch;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Allows decorating an existing Router
with filtering capabilities. Filters themselves should be supplied via the RouteMatchFilter
interface.
A filtered router can be enabled by implementing a BeanCreatedEventListener
for the existing Router
and decorating appropriately. See for example VersionAwareRouterListener
Author: Bogdan Oros, graemerocher See Also: Since: 1.1.0
/**
* Allows decorating an existing {@link Router} with filtering capabilities.
*
* <p>Filters themselves should be supplied via the {@link RouteMatchFilter} interface.</p>
*
* <p>A filtered router can be enabled by implementing a {@link io.micronaut.context.event.BeanCreatedEventListener} for
* the existing {@link Router} and decorating appropriately. See for example {@link io.micronaut.web.router.version.VersionAwareRouterListener}</p>
*
* @see RouteMatchFilter
* @author Bogdan Oros
* @author graemerocher
* @since 1.1.0
*/
public class FilteredRouter implements Router {
private final Router router;
private final RouteMatchFilter routeFilter;
Creates a decorated router for an existing router and RouteMatchFilter
. Params: - router – A
Router
to delegate to - routeFilter – A
RouteMatchFilter
to filter non matching routes
/**
* Creates a decorated router for an existing router and {@link RouteMatchFilter}.
*
* @param router A {@link Router} to delegate to
* @param routeFilter A {@link RouteMatchFilter} to filter non matching routes
*/
public FilteredRouter(Router router,
RouteMatchFilter routeFilter) {
this.router = router;
this.routeFilter = routeFilter;
}
@NonNull
@Override
public <T, R> Stream<UriRouteMatch<T, R>> findAny(@NonNull CharSequence uri, @Nullable HttpRequest<?> context) {
final Stream<UriRouteMatch<T, R>> matchStream = router.findAny(uri, context);
if (context != null) {
return matchStream.filter(routeFilter.filter(context));
}
return matchStream;
}
@Override
public Set<Integer> getExposedPorts() {
return router.getExposedPorts();
}
@Override
public void applyDefaultPorts(List<Integer> ports) {
router.applyDefaultPorts(ports);
}
@NonNull
@Override
public <T, R> Stream<UriRouteMatch<T, R>> find(@NonNull HttpMethod httpMethod, @NonNull CharSequence uri, @Nullable HttpRequest<?> context) {
final Stream<UriRouteMatch<T, R>> matchStream = router.find(httpMethod, uri, context);
if (context != null) {
return matchStream.filter(routeFilter.filter(context));
}
return matchStream;
}
@NonNull
@Override
public <T, R> List<UriRouteMatch<T, R>> findAllClosest(@NonNull HttpRequest<?> request) {
List<UriRouteMatch<T, R>> closestMatches = router.findAllClosest(request);
return closestMatches.stream().filter(routeFilter.filter(request))
.collect(Collectors.toList());
}
@NonNull
@Override
public <T, R> Stream<UriRouteMatch<T, R>> find(@NonNull HttpRequest<?> request, @NonNull CharSequence uri) {
return router.find(request, uri);
}
@NonNull
@Override
public Stream<UriRoute> uriRoutes() {
return router.uriRoutes();
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> route(@NonNull HttpMethod httpMethod, @NonNull CharSequence uri) {
return router.route(httpMethod, uri);
}
@Override
public <R> Optional<RouteMatch<R>> route(@NonNull HttpStatus status) {
return router.route(status);
}
@Override
public <R> Optional<RouteMatch<R>> route(@NonNull Class originatingClass, @NonNull HttpStatus status) {
return router.route(originatingClass, status);
}
@Override
public <R> Optional<RouteMatch<R>> route(@NonNull Throwable error) {
return router.route(error);
}
@Override
public <R> Optional<RouteMatch<R>> route(@NonNull Class originatingClass, @NonNull Throwable error) {
return router.route(originatingClass, error);
}
@Override
public <R> Optional<RouteMatch<R>> findErrorRoute(@NonNull Class<?> originatingClass, @NonNull Throwable error, HttpRequest<?> request) {
return router.findErrorRoute(originatingClass, error, request);
}
@Override
public <R> Optional<RouteMatch<R>> findErrorRoute(@NonNull Throwable error, HttpRequest<?> request) {
return router.findErrorRoute(error, request);
}
@Override
public <R> Optional<RouteMatch<R>> findStatusRoute(@NonNull Class<?> originatingClass, @NonNull HttpStatus status, HttpRequest<?> request) {
return router.findStatusRoute(originatingClass, status, request);
}
@Override
public <R> Optional<RouteMatch<R>> findStatusRoute(@NonNull HttpStatus status, HttpRequest<?> request) {
return router.findStatusRoute(status, request);
}
@NonNull
@Override
public List<HttpFilter> findFilters(@NonNull HttpRequest<?> request) {
return router.findFilters(request);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> GET(@NonNull CharSequence uri) {
return router.GET(uri);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> POST(@NonNull CharSequence uri) {
return router.POST(uri);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> PUT(@NonNull CharSequence uri) {
return router.PUT(uri);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> PATCH(@NonNull CharSequence uri) {
return router.PATCH(uri);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> DELETE(@NonNull CharSequence uri) {
return router.DELETE(uri);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> OPTIONS(@NonNull CharSequence uri) {
return router.OPTIONS(uri);
}
@Override
public <T, R> Optional<UriRouteMatch<T, R>> HEAD(@NonNull CharSequence uri) {
return router.HEAD(uri);
}
@NonNull
@Override
public <T, R> Stream<UriRouteMatch<T, R>> find(@NonNull HttpRequest<?> request) {
Stream<UriRouteMatch<T, R>> matches = router.find(request);
return matches.filter(routeFilter.filter(request));
}
}