Skip to content

Commit

Permalink
Merge pull request #35917 from snazy/route-order-constants
Browse files Browse the repository at this point in the history
  • Loading branch information
gastaldi authored Oct 2, 2023
2 parents 5199e18 + 938d9e3 commit cc02ea1
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 46 deletions.
27 changes: 27 additions & 0 deletions docs/src/main/asciidoc/http-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
|===
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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("/")) {
Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<RoutingContext> hotReplacementHandler;
Expand Down Expand Up @@ -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<HttpServerRequest> root = router;
Expand Down Expand Up @@ -402,7 +387,7 @@ public void finalizeRouter(BeanContainer container, Consumer<Route> 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);
Expand All @@ -412,7 +397,7 @@ public void finalizeRouter(BeanContainer container, Consumer<Route> 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<RoutingContext>() {
httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_BODY_HANDLER).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext routingContext) {
routingContext.request().resume();
Expand All @@ -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<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
Thread.currentThread().setContextClassLoader(currentCl);
hotReplacementHandler.handle(event);
}
});
httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_HOT_REPLACEMENT)
.handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
Thread.currentThread().setContextClassLoader(currentCl);
hotReplacementHandler.handle(event);
}
});
}
root = httpRouteRouter;
} else {
Expand All @@ -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<RoutingContext>() {
mainRouter.route().order(RouteConstants.ROUTE_ORDER_HOT_REPLACEMENT).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
Thread.currentThread().setContextClassLoader(currentCl);
Expand Down Expand Up @@ -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;
Expand All @@ -518,7 +505,7 @@ public void handle(HttpServerRequest event) {
Handler<HttpServerRequest> delegate = root;
root = HttpServerCommonHandlers.enforceDuplicatedContext(delegate);
if (httpConfiguration.recordRequestStartTime) {
httpRouteRouter.route().order(Integer.MIN_VALUE).handler(new Handler<RoutingContext>() {
httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_RECORD_START_TIME).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
event.put(REQUEST_START_TIME, System.nanoTime());
Expand All @@ -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) {
Expand All @@ -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<RoutingContext>() {
httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_COMPRESSION).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext ctx) {
// Add "Content-Encoding: identity" header that disables the compression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<RoutingContext>() {
httpRouteRouter.route().order(RouteConstants.ROUTE_ORDER_UPLOAD_LIMIT).handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
String lengthString = event.request().headers().get(HttpHeaderNames.CONTENT_LENGTH);
Expand Down Expand Up @@ -150,7 +151,7 @@ public static void applyHeaders(Map<String, HeaderConfig> 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<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
Expand All @@ -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<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down

0 comments on commit cc02ea1

Please sign in to comment.