Repository: quarkusio/quarkus
Issue: quarkus-resteasy-reactive PathMatcher allows any extra character in the end of valid path

### Describe the bug

when using **quarkus-resteasy-reactive**, appending any extra character in the end of a valid path doesn't result in 404 but instead gets to the existing valid route
making simple `@Path("hello")` resource, will return a response when calling /hello, but also /helloX (X = any character) and /helloX/, while the invalid paths should result in 404
appending more than 1 character results in a valid behaviour and returns 404
seems that the `PathMatcher` treats the last character as if it was a trailing slash since in some places in the code only the length of the remaining path part is checked (I suppose for performance reasons?)

**quarkus-resteasy** PathMatcher does behave as expected

### Expected behavior

`/hello` should return a response
`/helloX` and `/helloX/` should return 404 (X == any character)

### Actual behavior

`/hello` should return a response
`/helloX` and `/helloX/` return same response as `/hello`

### How to Reproduce?

create a starter quarkus project with quarkus-resteasy-reactive extension
add a simple hello resource

(kotlin version)
```
@Path("hello")
class HelloResource {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    fun hello() : String {
        return "Hello"
    }
}
```

### Output of `uname -a` or `ver`

Darwin MacBook-Pro.local 20.6.0 Darwin Kernel Version 20.6.0; root:xnu-7195.141.8~1/RELEASE_X86_64 x86_64

### Output of `java -version`

openjdk version "16.0.2" 2021-07-20; OpenJDK Runtime Environment Corretto-16.0.2.7.1 (build 16.0.2+7)

### GraalVM version (if different from Java)

-

### Quarkus version or git rev

2.6.3.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Gradle 6.9

### Additional information

_No response_

Changed files:
independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/mapping/RequestMapper.java
independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/path/RestPathTestCase.java

diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/mapping/RequestMapper.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/mapping/RequestMapper.java
index b2baf6c67dc..62b9c71d3f7 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/mapping/RequestMapper.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/mapping/RequestMapper.java
@@ -104,11 +104,13 @@ public RequestMatch<T> map(String path) {
                 params[paramCount] = null;
             }
             boolean fullMatch = matchPos == pathLength;
-            if (!prefixAllowed && !fullMatch) {
+            boolean doPrefixMatch = false;
+            if (!fullMatch) {
                 //according to the spec every template ends with (/.*)?
-                prefixAllowed = path.charAt(matchPos) == '/' && matchPos == pathLength - 1;
+                doPrefixMatch = (matchPos == 1 || path.charAt(matchPos) == '/') //matchPos == 1 corresponds to '/' as a root level match
+                        && (prefixAllowed || matchPos == pathLength - 1); //if prefix is allowed, or the remainder is only a trailing /
             }
-            if (matched && (fullMatch || prefixAllowed)) {
+            if (matched && (fullMatch || doPrefixMatch)) {
                 String remaining;
                 if (fullMatch) {
                     remaining = "";
diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/path/RestPathTestCase.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/path/RestPathTestCase.java
index 4cbf79afa1f..e7261aeac94 100644
--- a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/path/RestPathTestCase.java
+++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/path/RestPathTestCase.java
@@ -24,8 +24,9 @@ public void accept(ResteasyReactiveDeploymentManager.ScanStep scanStep) {
     @Test
     public void testRestPath() {
         RestAssured.basePath = "/";
-        RestAssured.when().get("/foo/hello").then().statusCode(200).body(Matchers.is("hello"));
         RestAssured.when().get("/foo/hello/nested").then().statusCode(200).body(Matchers.is("world hello"));
+        RestAssured.when().get("/foo/helloX").then().statusCode(404);
+        RestAssured.when().get("/foo/hello").then().statusCode(200).body(Matchers.is("hello"));
     }
 
     @Test