From 8c53a8a546c303329448167501c97e8ec75118fe Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Mon, 11 May 2020 09:15:43 +0200 Subject: [PATCH] Document how to resolve reactive route conflicts using the order attribute --- docs/src/main/asciidoc/reactive-routes.adoc | 38 +++++++++++++++ .../vertx/web/ConflictingRouteTest.java | 48 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/ConflictingRouteTest.java diff --git a/docs/src/main/asciidoc/reactive-routes.adoc b/docs/src/main/asciidoc/reactive-routes.adoc index 1159a816b40c0..fa8784941a75f 100644 --- a/docs/src/main/asciidoc/reactive-routes.adoc +++ b/docs/src/main/asciidoc/reactive-routes.adoc @@ -108,6 +108,44 @@ public void route(RoutingContext rc) { Each route can use different paths, methods... + +=== Handling conflicting routes + +You may end up with multiple routes matching a given path. +In the following example, both route matches `/accounts/me`: + +[source, java] +---- +@Route(path = "/accounts/:id", methods = HttpMethod.GET) +void getAccount(RoutingContext ctx) { + ... +} + +@Route(path = "/accounts/me", methods = HttpMethod.GET) +void getCurrentUserAccount(RoutingContext ctx) { + ... +} +---- + +As a consequence, the result is not the expected one as the first route is called with the path parameter `id` set to `me`. +To avoid the conflict, use the `order` attribute: + +[source, java] +---- +@Route(path = "/accounts/:id", methods = HttpMethod.GET, order = 2) +void getAccount(RoutingContext ctx) { + ... +} + +@Route(path = "/accounts/me", methods = HttpMethod.GET, order = 1) +void getCurrentUserAccount(RoutingContext ctx) { + ... +} +---- + +By giving a lower order to the second route, it gets evaluated first. +If the request path matches, it is invoked, otherwise the other routes are evaluated. + === `@RouteBase` This annotation can be used to configure some defaults for reactive routes declared on a class. diff --git a/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/ConflictingRouteTest.java b/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/ConflictingRouteTest.java new file mode 100644 index 0000000000000..4446f433c281e --- /dev/null +++ b/extensions/vertx-web/deployment/src/test/java/io/quarkus/vertx/web/ConflictingRouteTest.java @@ -0,0 +1,48 @@ +package io.quarkus.vertx.web; + +import static io.restassured.RestAssured.get; + +import javax.enterprise.context.ApplicationScoped; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.RoutingContext; + +public class ConflictingRouteTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(MyRoutes.class)); + + @Test + public void testRouteConflict() { + String neo = get("/conflict/neo").asString(); + Assertions.assertEquals("neo", neo); + + String me = get("/conflict/me").asString(); + Assertions.assertEquals("/me called", me); + + } + + @ApplicationScoped + public static class MyRoutes { + + @Route(path = "/conflict/:id", methods = HttpMethod.GET, order = 2) + void getAccount(RoutingContext ctx) { + ctx.response().end(ctx.pathParam("id")); + } + + @Route(path = "/conflict/me", methods = HttpMethod.GET, order = 1) + void getCurrentUserAccount(RoutingContext ctx) { + ctx.response().end("/me called"); + } + + } +}