diff --git a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java index f0f8cf38087..15d123eec75 100644 --- a/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java +++ b/nima/webserver/webserver/src/main/java/io/helidon/nima/webserver/http/HttpRouting.java @@ -47,13 +47,14 @@ public final class HttpRouting implements Routing { private final ServiceRoute rootRoute; private final ErrorHandlers errorHandlers; private final List features; + private final int maxReRouteCount; private HttpRouting(Builder builder) { this.errorHandlers = ErrorHandlers.create(builder.errorHandlers); this.filters = Filters.create(errorHandlers, List.copyOf(builder.filters)); this.rootRoute = builder.rootRules.build(); this.features = List.copyOf(builder.features); - + this.maxReRouteCount = builder.maxReRouteCount; } /** @@ -96,7 +97,7 @@ public static HttpRouting empty() { * @param response routing response */ public void route(ConnectionContext ctx, RoutingRequest request, RoutingResponse response) { - RoutingExecutor routingExecutor = new RoutingExecutor(ctx, rootRoute, request, response); + RoutingExecutor routingExecutor = new RoutingExecutor(ctx, rootRoute, request, response, maxReRouteCount); // we cannot throw an exception to the filters, as then the filter would not have information about actual status // code, so error handling is done in routing executor and for each filter filters.filter(ctx, request, response, routingExecutor); @@ -130,6 +131,7 @@ public static class Builder implements HttpRules, io.helidon.common.Builder features = new ArrayList<>(); private final Map, ErrorHandler> errorHandlers = new IdentityHashMap<>(); + private int maxReRouteCount = 10; private Builder() { } @@ -319,6 +321,21 @@ public Builder any(String pattern, Handler handler) { .path(pattern) .handler(handler)); } + + /** + * Maximal number of allowed re-routes within routing. + * + * @param maxReRouteCount + * @return updated builder + * + * @see io.helidon.nima.webserver.http.ServerResponse#reroute(String) + * @see io.helidon.nima.webserver.http.ServerResponse#reroute(String, io.helidon.common.uri.UriQuery) + */ + public Builder maxReRouteCount(int maxReRouteCount){ + this.maxReRouteCount = maxReRouteCount; + return this; + } + } private static final class RoutingExecutor implements Callable { @@ -326,15 +343,18 @@ private static final class RoutingExecutor implements Callable { private final RoutingRequest request; private final RoutingResponse response; private final ServiceRoute rootRoute; + private final int maxReRouteCount; private RoutingExecutor(ConnectionContext ctx, ServiceRoute rootRoute, RoutingRequest request, - RoutingResponse response) { + RoutingResponse response, + int maxReRouteCount) { this.ctx = ctx; this.rootRoute = rootRoute; this.request = request; this.response = response; + this.maxReRouteCount = maxReRouteCount; } @Override @@ -350,11 +370,12 @@ public Void call() throws Exception { } // rerouting, do the more heavyweight while loop - int counter = 0; + int counter = 1; while (result == RoutingResult.ROUTE) { counter++; - if (counter == 9) { - LOGGER.log(System.Logger.Level.ERROR, "Rerouted more than 10 times. Will not attempt further routing"); + if (counter == maxReRouteCount) { + LOGGER.log(System.Logger.Level.ERROR, "Rerouted more than " + maxReRouteCount + + " times. Will not attempt further routing"); throw new HttpException("Too many reroutes", Http.Status.INTERNAL_SERVER_ERROR_500, true); }