From 7ceb271b3314d7f7ccda62c798d7405d782dd348 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Wed, 23 Oct 2019 12:35:36 +0200 Subject: [PATCH] RESTEasy standalone - handle @ApplicationPath value correctly - application path value does not have to start with a slash - resource should not be served from both the root and the app path - resolves #4787 --- .../ResteasyStandaloneBuildStep.java | 62 ++++++++++++++----- .../ResteasyStandaloneRecorder.java | 21 ++++--- .../standalone/VertxRequestHandler.java | 8 +-- .../runtime/standalone/VertxUtil.java | 5 ++ 4 files changed, 69 insertions(+), 27 deletions(-) diff --git a/extensions/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java b/extensions/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java index 35b8f8802ddc19..a42b8a2f50b2e1 100644 --- a/extensions/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java +++ b/extensions/resteasy/deployment/src/main/java/io/quarkus/resteasy/deployment/ResteasyStandaloneBuildStep.java @@ -31,15 +31,25 @@ import io.quarkus.vertx.core.deployment.InternalWebVertxBuildItem; import io.quarkus.vertx.http.deployment.DefaultRouteBuildItem; import io.quarkus.vertx.http.deployment.RequireVirtualHttpBuildItem; +import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig; +import io.vertx.core.Handler; import io.vertx.ext.web.Route; +import io.vertx.ext.web.RoutingContext; public class ResteasyStandaloneBuildStep { + protected static final String META_INF_RESOURCES_SLASH = "META-INF/resources/"; protected static final String META_INF_RESOURCES = "META-INF/resources"; public static final class ResteasyStandaloneBuildItem extends SimpleBuildItem { + final String rootPath; + + public ResteasyStandaloneBuildItem(String rootPath) { + this.rootPath = rootPath; + } + } @BuildStep() @@ -49,31 +59,38 @@ public void staticInit(ResteasyStandaloneRecorder recorder, ResteasyDeploymentBuildItem deployment, ApplicationArchivesBuildItem applicationArchivesBuildItem, ResteasyInjectionReadyBuildItem resteasyInjectionReady, - HttpBuildTimeConfig httpBuildTimeConfig, + HttpBuildTimeConfig httpConfig, BuildProducer standalone) throws Exception { if (capabilities.isCapabilityPresent(Capabilities.SERVLET)) { return; } Set knownPaths = getClasspathResources(applicationArchivesBuildItem); + String rootPath = httpConfig.rootPath; + if (deployment != null) { - String rootPath = deployment.getRootPath(); - if (!httpBuildTimeConfig.rootPath.equals("/")) { - rootPath = httpBuildTimeConfig.rootPath + rootPath; + String deploymentPath = deployment.getRootPath(); + if (rootPath.endsWith("/")) { + if (deploymentPath.startsWith("/")) { + rootPath += deploymentPath.substring(1, deploymentPath.length()); + } else { + rootPath += deploymentPath; + } + } else if (!deploymentPath.equals("/")) { + if (!deploymentPath.startsWith("/")) { + rootPath += "/"; + } + rootPath += deploymentPath; } recorder.staticInit(deployment.getDeployment(), rootPath, knownPaths); + } else if (!knownPaths.isEmpty()) { - String rootPath = "/"; - if (!httpBuildTimeConfig.rootPath.equals("/")) { - rootPath = httpBuildTimeConfig.rootPath; - } recorder.staticInit(null, rootPath, knownPaths); } if (deployment != null || !knownPaths.isEmpty()) { - standalone.produce(new ResteasyStandaloneBuildItem()); + standalone.produce(new ResteasyStandaloneBuildItem(rootPath)); } - } /** @@ -170,24 +187,41 @@ public void accept(Path path) { public void boot(ShutdownContextBuildItem shutdown, ResteasyStandaloneRecorder recorder, BuildProducer feature, - BuildProducer routeProducer, + BuildProducer defaultRoutes, + BuildProducer routes, InternalWebVertxBuildItem vertx, BeanContainerBuildItem beanContainer, ResteasyStandaloneBuildItem standalone, - Optional requireVirtual) throws Exception { + Optional requireVirtual, + HttpBuildTimeConfig httpConfig) throws Exception { if (standalone == null) { return; } feature.produce(new FeatureBuildItem(FeatureBuildItem.RESTEASY)); + boolean isDefaultResourcesPath = standalone.rootPath.equals(httpConfig.rootPath); + if (!isDefaultResourcesPath) { + Handler handler = recorder.vertxRequestHandler(vertx.getVertx(), beanContainer.getValue()); + // Exact match for resources matched to the root path + routes.produce(new RouteBuildItem(standalone.rootPath, handler)); + String matchPath = standalone.rootPath; + if (matchPath.endsWith("/")) { + matchPath += "*"; + } else { + matchPath += "/*"; + } + // Match paths that begin with the root path + routes.produce(new RouteBuildItem(matchPath, handler)); + } + boolean isVirtual = requireVirtual.isPresent(); Consumer ut = recorder.start(vertx.getVertx(), shutdown, beanContainer.getValue(), - isVirtual); + isVirtual, isDefaultResourcesPath); - routeProducer.produce(new DefaultRouteBuildItem(ut)); + defaultRoutes.produce(new DefaultRouteBuildItem(ut)); } } diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/ResteasyStandaloneRecorder.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/ResteasyStandaloneRecorder.java index 5096d1fcd8ffaf..a78196372c6e22 100644 --- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/ResteasyStandaloneRecorder.java +++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/ResteasyStandaloneRecorder.java @@ -7,7 +7,6 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import org.jboss.logging.Logger; import org.jboss.resteasy.spi.ResteasyDeployment; import io.netty.buffer.ByteBuf; @@ -29,7 +28,6 @@ @Recorder public class ResteasyStandaloneRecorder { - private static final Logger log = Logger.getLogger("io.quarkus.resteasy"); public static final String META_INF_RESOURCES = "META-INF/resources"; /** @@ -90,10 +88,10 @@ public void staticInit(ResteasyDeployment dep, String path, Set known) { contextPath = path; } - public Consumer start(RuntimeValue vertxValue, + public Consumer start(RuntimeValue vertx, ShutdownContext shutdown, BeanContainer beanContainer, - boolean isVirtual) { + boolean isVirtual, boolean isDefaultResourcesPath) { shutdown.addShutdownTask(new Runnable() { @Override @@ -103,7 +101,6 @@ public void run() { } } }); - Vertx vertx = vertxValue.getValue(); useDirect = !isVirtual; List> handlers = new ArrayList<>(); @@ -147,10 +144,8 @@ public Handler get() { }); } - if (deployment != null) { - VertxRequestHandler requestHandler = new VertxRequestHandler(vertx, beanContainer, deployment, contextPath, - ALLOCATOR); - handlers.add(requestHandler); + if (deployment != null && isDefaultResourcesPath) { + handlers.add(vertxRequestHandler(vertx, beanContainer)); } return new Consumer() { @@ -163,4 +158,12 @@ public void accept(Route route) { }; } + public Handler vertxRequestHandler(RuntimeValue vertx, + BeanContainer beanContainer) { + if (deployment != null) { + return new VertxRequestHandler(vertx.getValue(), beanContainer, deployment, contextPath, ALLOCATOR); + } + return null; + } + } diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java index a8e67a580b994c..79973331ea9388 100644 --- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java +++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java @@ -34,7 +34,7 @@ public class VertxRequestHandler implements Handler { protected final Vertx vertx; protected final RequestDispatcher dispatcher; - protected final String servletMappingPrefix; + protected final String rootPath; protected final BufferAllocator allocator; protected final BeanContainer beanContainer; protected final CurrentIdentityAssociation association; @@ -42,13 +42,13 @@ public class VertxRequestHandler implements Handler { public VertxRequestHandler(Vertx vertx, BeanContainer beanContainer, ResteasyDeployment deployment, - String servletMappingPrefix, + String rootPath, BufferAllocator allocator) { this.vertx = vertx; this.beanContainer = beanContainer; this.dispatcher = new RequestDispatcher((SynchronousDispatcher) deployment.getDispatcher(), deployment.getProviderFactory(), null); - this.servletMappingPrefix = servletMappingPrefix; + this.rootPath = rootPath; this.allocator = allocator; Instance association = CDI.current().select(CurrentIdentityAssociation.class); this.association = association.isResolvable() ? association.get() : null; @@ -90,7 +90,7 @@ private void dispatch(RoutingContext routingContext, InputStream is, VertxOutput try { Context ctx = vertx.getOrCreateContext(); HttpServerRequest request = routingContext.request(); - ResteasyUriInfo uriInfo = VertxUtil.extractUriInfo(request, servletMappingPrefix); + ResteasyUriInfo uriInfo = VertxUtil.extractUriInfo(request, rootPath); ResteasyHttpHeaders headers = VertxUtil.extractHttpHeaders(request); HttpServerResponse response = request.response(); VertxHttpResponse vertxResponse = new VertxHttpResponse(request, dispatcher.getProviderFactory(), diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxUtil.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxUtil.java index 83ae68924659ad..72b62c7f43f63a 100644 --- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxUtil.java +++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxUtil.java @@ -44,6 +44,11 @@ public static ResteasyUriInfo extractUriInfo(HttpServerRequest req, String conte uriString = protocol + "://" + host + uri; } + // ResteasyUriInfo expects a context path to start with a "/" character + if (!contextPath.startsWith("/")) { + contextPath = "/" + contextPath; + } + return new ResteasyUriInfo(uriString, contextPath); }