diff --git a/packages/java/endpoint/src/main/java/com/vaadin/hilla/route/ClientRouteRegistry.java b/packages/java/endpoint/src/main/java/com/vaadin/hilla/route/ClientRouteRegistry.java index 5fc07b73f0..a571c3bbd2 100644 --- a/packages/java/endpoint/src/main/java/com/vaadin/hilla/route/ClientRouteRegistry.java +++ b/packages/java/endpoint/src/main/java/com/vaadin/hilla/route/ClientRouteRegistry.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.vaadin.flow.function.DeploymentConfiguration; import com.vaadin.hilla.route.records.ClientViewConfig; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -32,6 +33,8 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.Objects; +import java.util.stream.Stream; /** * Keeps track of registered client side routes. @@ -98,12 +101,23 @@ public void removeRoute(String route) { public ClientViewConfig getRouteByPath(String path) { final Set routes = registeredRoutes.keySet(); final AntPathMatcher pathMatcher = new AntPathMatcher(); - for (String route : routes) { - if (pathMatcher.match(route, path)) { - return registeredRoutes.get(route); - } - } - return null; + return Stream.of(addTrailingSlash(path), removeTrailingSlash(path)) + .map(p -> { + for (String route : routes) { + if (pathMatcher.match(route, p)) { + return registeredRoutes.get(route); + } + } + return null; + }).filter(Objects::nonNull).findFirst().orElse(null); + } + + private String addTrailingSlash(String path) { + return path.endsWith("/") ? path : path + '/'; + } + + private String removeTrailingSlash(String path) { + return path.endsWith("/") ? path.substring(0, path.length() - 1) : path; } /** diff --git a/packages/java/endpoint/src/test/java/com/vaadin/hilla/route/RouteUtilTest.java b/packages/java/endpoint/src/test/java/com/vaadin/hilla/route/RouteUtilTest.java index 65f4680ddf..be6b7ecbb5 100644 --- a/packages/java/endpoint/src/test/java/com/vaadin/hilla/route/RouteUtilTest.java +++ b/packages/java/endpoint/src/test/java/com/vaadin/hilla/route/RouteUtilTest.java @@ -190,4 +190,31 @@ public void test_login_required_on_page() { boolean actual = endpointUtil.isRouteAllowed(request); Assert.assertFalse(actual); } + + /** + * Verifies that the root route is allowed when login is not required, + * despite the mismatch between "/" and "". + */ + @Test + public void test_login_not_required_on_root() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRequestURI("/context/"); + request.setContextPath("/context"); + request.setUserPrincipal(null); + + ClientViewConfig config = new ClientViewConfig(); + config.setTitle("Root"); + config.setRolesAllowed(null); + config.setLoginRequired(false); + config.setRoute(""); + config.setLazy(false); + config.setAutoRegistered(false); + config.setMenu(null); + config.setChildren(null); + config.setRouteParameters(null); + registry.addRoute("", config); + + boolean actual = endpointUtil.isRouteAllowed(request); + Assert.assertTrue(actual); + } }