Skip to content

Commit

Permalink
RESTEasy standalone - handle @ApplicationPath value correctly
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
mkouba committed Oct 23, 2019
1 parent a225ca1 commit 7ceb271
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -49,31 +59,38 @@ public void staticInit(ResteasyStandaloneRecorder recorder,
ResteasyDeploymentBuildItem deployment,
ApplicationArchivesBuildItem applicationArchivesBuildItem,
ResteasyInjectionReadyBuildItem resteasyInjectionReady,
HttpBuildTimeConfig httpBuildTimeConfig,
HttpBuildTimeConfig httpConfig,
BuildProducer<ResteasyStandaloneBuildItem> standalone) throws Exception {
if (capabilities.isCapabilityPresent(Capabilities.SERVLET)) {
return;
}

Set<String> 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));
}

}

/**
Expand Down Expand Up @@ -170,24 +187,41 @@ public void accept(Path path) {
public void boot(ShutdownContextBuildItem shutdown,
ResteasyStandaloneRecorder recorder,
BuildProducer<FeatureBuildItem> feature,
BuildProducer<DefaultRouteBuildItem> routeProducer,
BuildProducer<DefaultRouteBuildItem> defaultRoutes,
BuildProducer<RouteBuildItem> routes,
InternalWebVertxBuildItem vertx,
BeanContainerBuildItem beanContainer,
ResteasyStandaloneBuildItem standalone,
Optional<RequireVirtualHttpBuildItem> requireVirtual) throws Exception {
Optional<RequireVirtualHttpBuildItem> 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<RoutingContext> 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<Route> ut = recorder.start(vertx.getVertx(),
shutdown,
beanContainer.getValue(),
isVirtual);
isVirtual, isDefaultResourcesPath);

routeProducer.produce(new DefaultRouteBuildItem(ut));
defaultRoutes.produce(new DefaultRouteBuildItem(ut));
}

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

/**
Expand Down Expand Up @@ -90,10 +88,10 @@ public void staticInit(ResteasyDeployment dep, String path, Set<String> known) {
contextPath = path;
}

public Consumer<Route> start(RuntimeValue<Vertx> vertxValue,
public Consumer<Route> start(RuntimeValue<Vertx> vertx,
ShutdownContext shutdown,
BeanContainer beanContainer,
boolean isVirtual) {
boolean isVirtual, boolean isDefaultResourcesPath) {

shutdown.addShutdownTask(new Runnable() {
@Override
Expand All @@ -103,7 +101,6 @@ public void run() {
}
}
});
Vertx vertx = vertxValue.getValue();
useDirect = !isVirtual;
List<Handler<RoutingContext>> handlers = new ArrayList<>();

Expand Down Expand Up @@ -147,10 +144,8 @@ public Handler<RoutingContext> 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<Route>() {

Expand All @@ -163,4 +158,12 @@ public void accept(Route route) {
};
}

public Handler<RoutingContext> vertxRequestHandler(RuntimeValue<Vertx> vertx,
BeanContainer beanContainer) {
if (deployment != null) {
return new VertxRequestHandler(vertx.getValue(), beanContainer, deployment, contextPath, ALLOCATOR);
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,21 @@ public class VertxRequestHandler implements Handler<RoutingContext> {

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;

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<CurrentIdentityAssociation> association = CDI.current().select(CurrentIdentityAssociation.class);
this.association = association.isResolvable() ? association.get() : null;
Expand Down Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit 7ceb271

Please sign in to comment.