diff --git a/docs/src/main/asciidoc/http-reference.adoc b/docs/src/main/asciidoc/http-reference.adoc index 0eb5d80a961a3..642c75c9212b5 100644 --- a/docs/src/main/asciidoc/http-reference.adoc +++ b/docs/src/main/asciidoc/http-reference.adoc @@ -590,3 +590,30 @@ link:https://undertow.io/undertow-docs/undertow-docs-2.0.0/index.html#predicates === web.xml If you are using a `web.xml` file as your configuration file, you can place it in the `src/main/resources/META-INF` directory. + +=== Built-in route order values + +Route order values are the values that are specified via Vert.x route `io.vertx.ext.web.Route.order(int)` function. + +Quarkus registers a couple of routes with specific order values. +The constants are defined in the `io.quarkus.vertx.http.runtime.RouteConstants` class and listed in the table below. +A custom route should define the order of value 20000 or higher so that it does not interfere with the functionality provided by Quarkus and extensions. + +Route order constants defined in `io.quarkus.vertx.http.runtime.RouteConstants` and known extensions: + +[cols="1,1,3"] +|=== +| Route order value| Constant name| Origin +| `Integer.MIN_VALUE` | `ROUTE_ORDER_ACCESS_LOG_HANDLER` | Access-log handler, if enabled in the configuration. +| `Integer.MIN_VALUE` | `ROUTE_ORDER_RECORD_START_TIME` | Handler adding the start-time, if enabled in the configuration. +| `Integer.MIN_VALUE` | `ROUTE_ORDER_HOT_REPLACEMENT` | -replacement body handler. +| `Integer.MIN_VALUE` | `ROUTE_ORDER_BODY_HANDLER_MANAGEMENT` | Body handler for the management router. +| `Integer.MIN_VALUE` | `ROUTE_ORDER_HEADERS` | Handlers that add headers specified in the configuration. +| `Integer.MIN_VALUE` | `ROUTE_ORDER_CORS_MANAGEMENT` | CORS-Origin handler of the management router. +| `Integer.MIN_VALUE + 1` | `ROUTE_ORDER_BODY_HANDLER` | Body handler. +| `-2` | `ROUTE_ORDER_UPLOAD_LIMIT` | Route that enforces the upload body size limit. +| `0` | `ROUTE_ORDER_COMPRESSION` | Compression handler. +| `1000` | `ROUTE_ORDER_BEFORE_DEFAULT` | Route with priority over the default route (add an offset from this value). +| `10000` | `ROUTE_ORDER_DEFAULT` | Default route order (i.e. Static Resources, Servlet). +| `20000` | `ROUTE_ORDER_AFTER_DEFAULT` | Route without priority over the default route (add an offset from this value) +|=== diff --git a/extensions/resteasy-classic/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java b/extensions/resteasy-classic/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java index 73b99d8406866..6bcd316a4a08e 100644 --- a/extensions/resteasy-classic/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java +++ b/extensions/resteasy-classic/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java @@ -41,7 +41,7 @@ import io.quarkus.vertx.http.deployment.RequireVirtualHttpBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig; -import io.quarkus.vertx.http.runtime.VertxHttpRecorder; +import io.quarkus.vertx.http.runtime.RouteConstants; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; @@ -136,7 +136,7 @@ public void boot(ShutdownContextBuildItem shutdown, routes.produce( RouteBuildItem.builder() .orderedRoute(standalone.deploymentRootPath, - VertxHttpRecorder.AFTER_DEFAULT_ROUTE_ORDER_MARK + REST_ROUTE_ORDER_OFFSET) + RouteConstants.ROUTE_ORDER_AFTER_DEFAULT + REST_ROUTE_ORDER_OFFSET) .handler(handler).build()); String matchPath = standalone.deploymentRootPath; if (matchPath.endsWith("/")) { @@ -146,7 +146,7 @@ public void boot(ShutdownContextBuildItem shutdown, } // Match paths that begin with the deployment path routes.produce(RouteBuildItem.builder() - .orderedRoute(matchPath, VertxHttpRecorder.AFTER_DEFAULT_ROUTE_ORDER_MARK + REST_ROUTE_ORDER_OFFSET) + .orderedRoute(matchPath, RouteConstants.ROUTE_ORDER_AFTER_DEFAULT + REST_ROUTE_ORDER_OFFSET) .handler(handler).build()); recorder.start(shutdown, requireVirtual.isPresent()); diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java index c52f28315e392..2b018c4247b58 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java @@ -203,7 +203,7 @@ import io.quarkus.vertx.http.deployment.FilterBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig; -import io.quarkus.vertx.http.runtime.VertxHttpRecorder; +import io.quarkus.vertx.http.runtime.RouteConstants; import io.vertx.core.Handler; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; @@ -1251,11 +1251,11 @@ public void setupDeployment(BeanContainerBuildItem beanContainerBuildItem, .produce(new ResteasyReactiveDeploymentInfoBuildItem(deploymentInfo)); boolean servletPresent = false; - int order = VertxHttpRecorder.AFTER_DEFAULT_ROUTE_ORDER_MARK + REST_ROUTE_ORDER_OFFSET; + int order = RouteConstants.ROUTE_ORDER_AFTER_DEFAULT + REST_ROUTE_ORDER_OFFSET; if (capabilities.isPresent("io.quarkus.servlet")) { //if servlet is present we run RR before the default route //otherwise we run after it - order = VertxHttpRecorder.BEFORE_DEFAULT_ROUTE_ORDER_MARK + REST_ROUTE_ORDER_OFFSET; + order = RouteConstants.ROUTE_ORDER_BEFORE_DEFAULT + REST_ROUTE_ORDER_OFFSET; servletPresent = true; } diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/RouteConstants.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/RouteConstants.java new file mode 100644 index 0000000000000..6d00a3afa9b07 --- /dev/null +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/RouteConstants.java @@ -0,0 +1,62 @@ +package io.quarkus.vertx.http.runtime; + +/** + * Route order value constants used in Quarkus, update {@code reactive-routes.adoc} when changing this class. + */ +@SuppressWarnings("JavadocDeclaration") +public final class RouteConstants { + private RouteConstants() { + } + + /** + * Order value ({@value #ROUTE_ORDER_ACCESS_LOG_HANDLER}) for the access-log handler, if enabled in the configuration. + */ + public static final int ROUTE_ORDER_ACCESS_LOG_HANDLER = Integer.MIN_VALUE; + /** + * Order value ({@value #ROUTE_ORDER_RECORD_START_TIME}) for the handler adding the start-time, if enabled in the + * configuration. + */ + public static final int ROUTE_ORDER_RECORD_START_TIME = Integer.MIN_VALUE; + /** + * Order value ({@value #ROUTE_ORDER_HOT_REPLACEMENT}) for the hot-replacement body handler. + */ + public static final int ROUTE_ORDER_HOT_REPLACEMENT = Integer.MIN_VALUE; + /** + * Order value ({@value #ROUTE_ORDER_BODY_HANDLER_MANAGEMENT}) for the body handler for the management router. + */ + public static final int ROUTE_ORDER_BODY_HANDLER_MANAGEMENT = Integer.MIN_VALUE; + /** + * Order value ({@value #ROUTE_ORDER_HEADERS}) for the handlers that add headers specified in the configuration. + */ + public static final int ROUTE_ORDER_HEADERS = Integer.MIN_VALUE; + /** + * Order value ({@value #ROUTE_ORDER_CORS_MANAGEMENT}) for the CORS-Origin handler of the management router. + */ + public static final int ROUTE_ORDER_CORS_MANAGEMENT = Integer.MIN_VALUE; + /** + * Order value ({@value #ROUTE_ORDER_BODY_HANDLER}) for the body handler. + */ + public static final int ROUTE_ORDER_BODY_HANDLER = Integer.MIN_VALUE + 1; + /** + * Order value ({@value #ROUTE_ORDER_UPLOAD_LIMIT}) for the route that enforces the upload body size limit. + */ + public static final int ROUTE_ORDER_UPLOAD_LIMIT = -2; + /** + * Order value ({@value #ROUTE_ORDER_COMPRESSION}) for the compression handler. + */ + public static final int ROUTE_ORDER_COMPRESSION = 0; + /** + * Order value ({@value #ROUTE_ORDER_BEFORE_DEFAULT}) for route with priority over the default route (add an offset from + * this value) + */ + public static final int ROUTE_ORDER_BEFORE_DEFAULT = 1_000; + /** + * Default route order (i.e. Static Resources, Servlet): ({@value #ROUTE_ORDER_DEFAULT}) + */ + public static final int ROUTE_ORDER_DEFAULT = 10_000; + /** + * Order value ({@value #ROUTE_ORDER_AFTER_DEFAULT}) for route without priority over the default route (add an offset + * from this value) + */ + public static final int ROUTE_ORDER_AFTER_DEFAULT = 20_000; +} diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java index 1f90288598153..fbcb893f48b9d 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java @@ -117,21 +117,6 @@ public class VertxHttpRecorder { private static final String DISABLE_WEBSOCKETS_PROP_NAME = "vertx.disableWebsockets"; - /** - * Order mark for route with priority over the default route (add an offset from this mark) - **/ - public static final int BEFORE_DEFAULT_ROUTE_ORDER_MARK = 1_000; - - /** - * Default route order (i.e. Static Resources, Servlet) - **/ - public static final int DEFAULT_ROUTE_ORDER = 10_000; - - /** - * Order mark for route without priority over the default route (add an offset from this mark) - **/ - public static final int AFTER_DEFAULT_ROUTE_ORDER_MARK = 20_000; - private static final Logger LOGGER = Logger.getLogger(VertxHttpRecorder.class.getName()); private static volatile Handler hotReplacementHandler; @@ -273,7 +258,7 @@ public static void startServerAfterFailedStart() { } Router router = Router.router(vertx); if (hotReplacementHandler != null) { - router.route().order(Integer.MIN_VALUE).blockingHandler(hotReplacementHandler); + router.route().order(RouteConstants.ROUTE_ORDER_HOT_REPLACEMENT).blockingHandler(hotReplacementHandler); } Handler root = router; @@ -402,7 +387,7 @@ public void finalizeRouter(BeanContainer container, Consumer defaultRoute } if (defaultRouteHandler != null) { - defaultRouteHandler.accept(httpRouteRouter.route().order(DEFAULT_ROUTE_ORDER)); + defaultRouteHandler.accept(httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_DEFAULT)); } applyCompression(httpBuildTimeConfig.enableCompression, httpRouteRouter); @@ -412,7 +397,7 @@ public void finalizeRouter(BeanContainer container, Consumer defaultRoute if (requireBodyHandler) { //if this is set then everything needs the body handler installed //TODO: config etc - httpRouteRouter.route().order(Integer.MIN_VALUE + 1).handler(new Handler() { + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_BODY_HANDLER).handler(new Handler() { @Override public void handle(RoutingContext routingContext) { routingContext.request().resume(); @@ -433,13 +418,14 @@ public void handle(RoutingContext routingContext) { if (hotReplacementHandler != null) { //recorders are always executed in the current CL ClassLoader currentCl = Thread.currentThread().getContextClassLoader(); - httpRouteRouter.route().order(Integer.MIN_VALUE).handler(new Handler() { - @Override - public void handle(RoutingContext event) { - Thread.currentThread().setContextClassLoader(currentCl); - hotReplacementHandler.handle(event); - } - }); + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_HOT_REPLACEMENT) + .handler(new Handler() { + @Override + public void handle(RoutingContext event) { + Thread.currentThread().setContextClassLoader(currentCl); + hotReplacementHandler.handle(event); + } + }); } root = httpRouteRouter; } else { @@ -449,7 +435,7 @@ public void handle(RoutingContext event) { if (hotReplacementHandler != null) { ClassLoader currentCl = Thread.currentThread().getContextClassLoader(); - mainRouter.route().order(Integer.MIN_VALUE).handler(new Handler() { + mainRouter.route().order(RouteConstants.ROUTE_ORDER_HOT_REPLACEMENT).handler(new Handler() { @Override public void handle(RoutingContext event) { Thread.currentThread().setContextClassLoader(currentCl); @@ -484,15 +470,16 @@ public void handle(RoutingContext event) { AccessLogHandler handler = new AccessLogHandler(receiver, accessLog.pattern, getClass().getClassLoader(), accessLog.excludePattern); if (rootPath.equals("/") || nonRootPath.equals("/")) { - mainRouterRuntimeValue.orElse(httpRouterRuntimeValue).getValue().route().order(Integer.MIN_VALUE) + mainRouterRuntimeValue.orElse(httpRouterRuntimeValue).getValue().route() + .order(RouteConstants.ROUTE_ORDER_ACCESS_LOG_HANDLER) .handler(handler); } else if (nonRootPath.startsWith(rootPath)) { - httpRouteRouter.route().order(Integer.MIN_VALUE).handler(handler); + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_ACCESS_LOG_HANDLER).handler(handler); } else if (rootPath.startsWith(nonRootPath)) { - frameworkRouter.getValue().route().order(Integer.MIN_VALUE).handler(handler); + frameworkRouter.getValue().route().order(RouteConstants.ROUTE_ORDER_ACCESS_LOG_HANDLER).handler(handler); } else { - httpRouteRouter.route().order(Integer.MIN_VALUE).handler(handler); - frameworkRouter.getValue().route().order(Integer.MIN_VALUE).handler(handler); + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_ACCESS_LOG_HANDLER).handler(handler); + frameworkRouter.getValue().route().order(RouteConstants.ROUTE_ORDER_ACCESS_LOG_HANDLER).handler(handler); } quarkusWrapperNeeded = true; @@ -518,7 +505,7 @@ public void handle(HttpServerRequest event) { Handler delegate = root; root = HttpServerCommonHandlers.enforceDuplicatedContext(delegate); if (httpConfiguration.recordRequestStartTime) { - httpRouteRouter.route().order(Integer.MIN_VALUE).handler(new Handler() { + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_RECORD_START_TIME).handler(new Handler() { @Override public void handle(RoutingContext event) { event.put(REQUEST_START_TIME, System.nanoTime()); @@ -539,9 +526,10 @@ public void handle(RoutingContext event) { mr.route().last().failureHandler( new QuarkusErrorHandler(launchMode.isDevOrTest(), httpConfiguration.unhandledErrorContentTypeDefault)); - mr.route().order(Integer.MIN_VALUE).handler(createBodyHandlerForManagementInterface()); + mr.route().order(RouteConstants.ROUTE_ORDER_BODY_HANDLER_MANAGEMENT) + .handler(createBodyHandlerForManagementInterface()); // We can use "*" here as the management interface is not expected to be used publicly. - mr.route().order(Integer.MIN_VALUE).handler(CorsHandler.create().addOrigin("*")); + mr.route().order(RouteConstants.ROUTE_ORDER_CORS_MANAGEMENT).handler(CorsHandler.create().addOrigin("*")); HttpServerCommonHandlers.applyFilters(managementConfiguration.getValue().filter, mr); for (Filter filter : managementInterfaceFilterList) { @@ -562,7 +550,7 @@ public void handle(RoutingContext event) { private void applyCompression(boolean enableCompression, Router httpRouteRouter) { if (enableCompression) { - httpRouteRouter.route().order(0).handler(new Handler() { + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_COMPRESSION).handler(new Handler() { @Override public void handle(RoutingContext ctx) { // Add "Content-Encoding: identity" header that disables the compression diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerCommonHandlers.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerCommonHandlers.java index 562611de71eb4..820e6390b9b4a 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerCommonHandlers.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerCommonHandlers.java @@ -16,6 +16,7 @@ import io.quarkus.vertx.http.runtime.HeaderConfig; import io.quarkus.vertx.http.runtime.ProxyConfig; import io.quarkus.vertx.http.runtime.ResumingRequestWrapper; +import io.quarkus.vertx.http.runtime.RouteConstants; import io.quarkus.vertx.http.runtime.ServerLimitsConfig; import io.quarkus.vertx.http.runtime.TrustedProxyCheck; import io.quarkus.vertx.http.runtime.VertxHttpRecorder; @@ -33,7 +34,7 @@ public static void enforceMaxBodySize(ServerLimitsConfig limits, Router httpRout if (limits.maxBodySize.isPresent()) { long limit = limits.maxBodySize.get().asLongValue(); Long limitObj = limit; - httpRouteRouter.route().order(-2).handler(new Handler() { + httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_UPLOAD_LIMIT).handler(new Handler() { @Override public void handle(RoutingContext event) { String lengthString = event.request().headers().get(HttpHeaderNames.CONTENT_LENGTH); @@ -150,7 +151,7 @@ public static void applyHeaders(Map headers, Router httpRo var config = entry.getValue(); if (config.methods.isEmpty()) { httpRouteRouter.route(config.path) - .order(Integer.MIN_VALUE) + .order(RouteConstants.ROUTE_ORDER_HEADERS) .handler(new Handler() { @Override public void handle(RoutingContext event) { @@ -161,7 +162,7 @@ public void handle(RoutingContext event) { } else { for (String method : config.methods.get()) { httpRouteRouter.route(HttpMethod.valueOf(method.toUpperCase(Locale.ROOT)), config.path) - .order(Integer.MIN_VALUE) + .order(RouteConstants.ROUTE_ORDER_HEADERS) .handler(new Handler() { @Override public void handle(RoutingContext event) { diff --git a/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/UploadRoute.java b/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/UploadRoute.java index 0a06dddc9c87d..2ca384f0ebea5 100644 --- a/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/UploadRoute.java +++ b/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/UploadRoute.java @@ -6,6 +6,7 @@ import jakarta.enterprise.event.Observes; import io.quarkus.runtime.StartupEvent; +import io.quarkus.vertx.http.runtime.RouteConstants; import io.quarkus.vertx.http.runtime.ServerLimitsConfig; import io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers; import io.vertx.core.buffer.Buffer; @@ -21,11 +22,12 @@ public class UploadRoute { /** * Installs two POST-routes - one that bypasses the body-length limit using {@code order(-3)} - * ({@link HttpServerCommonHandlers#enforceMaxBodySize(ServerLimitsConfig, Router)} uses {@code order(-2)}) and one that + * ({@link HttpServerCommonHandlers#enforceMaxBodySize(ServerLimitsConfig, Router)} uses + * {@value RouteConstants#ROUTE_ORDER_UPLOAD_LIMIT} for {@link io.vertx.ext.web.Route#order(int)}) and one that * does not bypass body-size enforcement. */ void installRoute(@Observes StartupEvent startupEvent, Router router) { - router.post("/unlimited-upload").order(-3).handler(UploadHandler::newRequest); + router.post("/unlimited-upload").order(RouteConstants.ROUTE_ORDER_UPLOAD_LIMIT - 1).handler(UploadHandler::newRequest); router.post("/limited-upload").handler(UploadHandler::newRequest); }