Repository: vert-x3/vertx-web
Issue: Template engine not working for parametrized paths like "/:project/"

### Version

4.0.0.Beta3

### Context

I am trying to use a template for this routing:

```
router
                .route()
                .path("/:project/")
                .produces("text/html")
                .handler(routingContext -> {
                    @Nullable String projectName = routingContext.request().getParam("project");
                        routingContext.put("projectName",projectName);
                        routingContext.next();
                    }
                })
                .handler(templateHandler);
```


### Do you have a reproducer?

I created a test that shows the problem. The result is a java.lang.StringIndexOutOfBoundsException:

https://github.com/paweld2/vertx-web/commit/ea2fed6591f449da614ace36e4a4deab89774bc5

### Steps to reproduce

The test shows the resulting exception. To reproduce on a project

1. Create a routing to "/:product" and add the template hander as next
2. Call "/test1/"
3. The result is a exception java.lang.StringIndexOutOfBoundsException

### Extra

Maybe a option to select a target template independently of the request path could be usefull here.


Changed files:
vertx-web/src/test/java/io/vertx/ext/web/templ/TemplateTest.java, vertx-web/src/main/java/io/vertx/ext/web/impl/Utils.java

diff --git a/vertx-web/src/main/java/io/vertx/ext/web/impl/Utils.java b/vertx-web/src/main/java/io/vertx/ext/web/impl/Utils.java
index 4e8c1ec6e..2425fe96b 100644
--- a/vertx-web/src/main/java/io/vertx/ext/web/impl/Utils.java
+++ b/vertx-web/src/main/java/io/vertx/ext/web/impl/Utils.java
@@ -55,6 +55,19 @@ public class Utils extends io.vertx.core.impl.Utils {
   }
 
   public static String pathOffset(String path, RoutingContext context) {
+    final String rest = context.pathParam("*");
+    if (rest != null) {
+      // normalize
+      if (rest.length() > 0) {
+        if (rest.charAt(0) == '/') {
+          return rest;
+        } else {
+          return "/" + rest;
+        }
+      } else {
+        return "/";
+      }
+    }
     int prefixLen = 0;
     String mountPoint = context.mountPoint();
     if (mountPoint != null) {
diff --git a/vertx-web/src/test/java/io/vertx/ext/web/templ/TemplateTest.java b/vertx-web/src/test/java/io/vertx/ext/web/templ/TemplateTest.java
index 16f9bc293..e109eddfb 100644
--- a/vertx-web/src/test/java/io/vertx/ext/web/templ/TemplateTest.java
+++ b/vertx-web/src/test/java/io/vertx/ext/web/templ/TemplateTest.java
@@ -87,6 +87,25 @@ public class TemplateTest extends WebTestBase {
     await();
   }
 
+  @Test
+  public void testTemplateEngineWithPathVariables() throws Exception {
+    TemplateEngine engine = new TestEngine(false);
+    router.route().handler(context -> {
+      context.put("foo", "badger");
+      context.put("bar", "fox");
+      context.next();
+    });
+    router.route("/:project/*").handler(TemplateHandler.create(engine, "somedir", "text/html"));
+    String expected =
+      "<html>\\n" +
+        "<body>\\n" +
+        "<h1>Test template</h1>\\n" +
+        "foo is badger bar is fox<br>\\n" +
+        "</body>\\n" +
+        "</html>";
+    testRequest(HttpMethod.GET, "/1/test-template.html", 200, "OK", expected);
+  }
+
   @Test
   public void testRenderDirectly() throws Exception {
     TemplateEngine engine = new TestEngine(false);
@@ -158,6 +177,5 @@ public class TemplateTest extends WebTestBase {
         handler.handle(Future.succeededFuture(Buffer.buffer(rendered)));
       }
     }
-
   }
 }