diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml
index 32eff33ff677c9..211a464ecf3321 100644
--- a/bom/runtime/pom.xml
+++ b/bom/runtime/pom.xml
@@ -24,7 +24,7 @@
0.2.0
0.0.12
0.34.0
- 3.0.0.Final
+ 3.0.1.Final
1.0.0.Final
1.3
1.0.1
diff --git a/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java b/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java
index f9775d62682b08..3dd6edb748e88f 100644
--- a/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java
+++ b/extensions/keycloak-authorization/deployment/src/main/java/io/quarkus/keycloak/pep/deployment/KeycloakPolicyEnforcerBuildStep.java
@@ -13,6 +13,7 @@
import io.quarkus.oidc.OIDCException;
import io.quarkus.oidc.runtime.OidcBuildTimeConfig;
import io.quarkus.oidc.runtime.OidcConfig;
+import io.quarkus.vertx.http.deployment.RequireBodyHandlerBuildItem;
public class KeycloakPolicyEnforcerBuildStep {
@@ -21,6 +22,12 @@ FeatureBuildItem featureBuildItem() {
return new FeatureBuildItem(FeatureBuildItem.KEYCLOAK_AUTHORIZATION);
}
+ @BuildStep
+ RequireBodyHandlerBuildItem requireBody() {
+ //TODO: this should only be produced if required, ask Pedro about config for this
+ return new RequireBodyHandlerBuildItem();
+ }
+
@BuildStep
public AdditionalBeanBuildItem beans(KeycloakPolicyEnforcerConfig config) {
if (config.policyEnforcer.enable) {
diff --git a/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/VertxHttpFacade.java b/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/VertxHttpFacade.java
index 825d0993b1306e..674c7daa8b476e 100644
--- a/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/VertxHttpFacade.java
+++ b/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/VertxHttpFacade.java
@@ -1,6 +1,5 @@
package io.quarkus.keycloak.pep.runtime;
-import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@@ -11,8 +10,6 @@
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.security.cert.X509Certificate;
-import io.quarkus.vertx.http.runtime.VertxInputStream;
-import io.vertx.core.http.HttpHeaders;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.OIDCHttpFacade;
import org.keycloak.adapters.spi.AuthenticationError;
@@ -25,6 +22,7 @@
import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.security.credential.TokenCredential;
import io.quarkus.security.identity.SecurityIdentity;
+import io.quarkus.vertx.http.runtime.VertxInputStream;
import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
@@ -109,15 +107,7 @@ public Cookie getCookie(String cookieName) {
@Override
public String getHeader(String name) {
- String value = request.getHeader(name);
-
- if (name.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE.toString())) {
- if (value.indexOf(';') != -1) {
- return value.substring(0, value.indexOf(';'));
- }
- }
-
- return value;
+ return request.getHeader(name);
}
@Override
@@ -133,15 +123,13 @@ public InputStream getInputStream() {
@Override
public InputStream getInputStream(boolean buffered) {
try {
- if (routingContext.get("quarkus.request.inputstream") != null) {
- return routingContext.get("quarkus.request.inputstream");
+ if (routingContext.getBody() != null) {
+ return new ByteArrayInputStream(routingContext.getBody().getBytes());
}
-
- BufferedInputStream stream = new BufferedInputStream(new VertxInputStream(request));
-
- routingContext.put("quarkus.request.inputstream", stream);
-
- return stream;
+ if (routingContext.request().isEnded()) {
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ return new VertxInputStream(request);
} catch (Exception e) {
throw new RuntimeException(e);
}
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 fb81b825c1ba09..ccd63565410d40 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
@@ -1,5 +1,6 @@
package io.quarkus.resteasy.runtime.standalone;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -7,7 +8,6 @@
import javax.enterprise.inject.spi.CDI;
import javax.ws.rs.core.SecurityContext;
-import io.quarkus.vertx.http.runtime.VertxInputStream;
import org.jboss.logging.Logger;
import org.jboss.resteasy.core.ResteasyContext;
import org.jboss.resteasy.core.SynchronousDispatcher;
@@ -20,6 +20,7 @@
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.security.identity.CurrentIdentityAssociation;
import io.quarkus.vertx.http.runtime.CurrentVertxRequest;
+import io.quarkus.vertx.http.runtime.VertxInputStream;
import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
import io.vertx.core.Context;
import io.vertx.core.Handler;
@@ -64,9 +65,8 @@ public void handle(RoutingContext request) {
// otherwise request handlers may not get set up before request ends
InputStream is;
try {
- if (request.get("quarkus.request.inputstream") != null) {
- is = request.get("quarkus.request.inputstream");
- is.mark(0);
+ if (request.getBody() != null) {
+ is = new ByteArrayInputStream(request.getBody().getBytes());
} else {
is = new VertxInputStream(request.request());
}
diff --git a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
index f9e7394440a1bf..d66f8d71f3e487 100644
--- a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
+++ b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
@@ -353,7 +353,8 @@ public void run() {
return new Handler() {
@Override
public void handle(RoutingContext event) {
- VertxHttpExchange exchange = new VertxHttpExchange(event.request(), allocator, executorService, event);
+ VertxHttpExchange exchange = new VertxHttpExchange(event.request(), allocator, executorService, event,
+ event.getBody());
Optional maxBodySize = httpConfiguration.limits.maxBodySize;
if (maxBodySize.isPresent()) {
exchange.setMaxEntitySize(maxBodySize.get().asLongValue());
diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/BodyHandlerBuildItem.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/BodyHandlerBuildItem.java
new file mode 100644
index 00000000000000..c5743fcd303850
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/BodyHandlerBuildItem.java
@@ -0,0 +1,17 @@
+package io.quarkus.vertx.http.deployment;
+
+import io.quarkus.builder.item.SimpleBuildItem;
+import io.vertx.core.Handler;
+import io.vertx.ext.web.RoutingContext;
+
+public final class BodyHandlerBuildItem extends SimpleBuildItem {
+ private final Handler handler;
+
+ public BodyHandlerBuildItem(Handler handler) {
+ this.handler = handler;
+ }
+
+ public Handler getHandler() {
+ return handler;
+ }
+}
diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RequireBodyHandlerBuildItem.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RequireBodyHandlerBuildItem.java
new file mode 100644
index 00000000000000..dbfd8541499a3d
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RequireBodyHandlerBuildItem.java
@@ -0,0 +1,10 @@
+package io.quarkus.vertx.http.deployment;
+
+import io.quarkus.builder.item.MultiBuildItem;
+
+/**
+ * This is a marker that indicates that the body handler should be installed
+ * on all routes, as an extension requires the request to be fully buffered.
+ */
+public final class RequireBodyHandlerBuildItem extends MultiBuildItem {
+}
diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/VertxHttpProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/VertxHttpProcessor.java
index 2dcebfca9208d3..344f6a18cfd907 100644
--- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/VertxHttpProcessor.java
+++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/VertxHttpProcessor.java
@@ -35,8 +35,10 @@
import io.quarkus.vertx.http.runtime.VertxHttpRecorder;
import io.quarkus.vertx.http.runtime.cors.CORSRecorder;
import io.quarkus.vertx.http.runtime.filters.Filter;
+import io.vertx.core.Handler;
import io.vertx.core.impl.VertxImpl;
import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
class VertxHttpProcessor {
@@ -97,6 +99,12 @@ VertxWebRouterBuildItem initializeRouter(VertxHttpRecorder recorder,
return new VertxWebRouterBuildItem(router);
}
+ @BuildStep
+ @Record(ExecutionTime.RUNTIME_INIT)
+ BodyHandlerBuildItem bodyHandler(VertxHttpRecorder recorder, HttpConfiguration httpConfiguration) {
+ return new BodyHandlerBuildItem(recorder.createBodyHandler(httpConfiguration));
+ }
+
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
ServiceStartBuildItem finalizeRouter(
@@ -106,7 +114,9 @@ ServiceStartBuildItem finalizeRouter(
List defaultRoutes, List filters,
VertxWebRouterBuildItem router, EventLoopCountBuildItem eventLoopCount,
HttpBuildTimeConfig httpBuildTimeConfig, HttpConfiguration httpConfiguration,
- BuildProducer reflectiveClass, List websocketSubProtocols)
+ BuildProducer reflectiveClass, List websocketSubProtocols,
+ List requireBodyHandlerBuildItems,
+ BodyHandlerBuildItem bodyHandlerBuildItem)
throws BuildException, IOException {
Optional defaultRoute;
if (defaultRoutes == null || defaultRoutes.isEmpty()) {
@@ -124,9 +134,13 @@ ServiceStartBuildItem finalizeRouter(
.filter(f -> f.getHandler() != null)
.map(FilterBuildItem::toFilter).collect(Collectors.toList());
+ //if the body handler is required then we know it is installed for all routes, so we don't need to register it here
+ Handler bodyHandler = requireBodyHandlerBuildItems.isEmpty() ? bodyHandlerBuildItem.getHandler() : null;
+
recorder.finalizeRouter(beanContainer.getValue(),
defaultRoute.map(DefaultRouteBuildItem::getRoute).orElse(null),
- listOfFilters, vertx.getVertx(), router.getRouter(), httpBuildTimeConfig.rootPath, launchMode.getLaunchMode());
+ listOfFilters, vertx.getVertx(), router.getRouter(), httpBuildTimeConfig.rootPath, launchMode.getLaunchMode(),
+ !requireBodyHandlerBuildItems.isEmpty(), bodyHandler);
boolean startVirtual = requireVirtual.isPresent() || httpBuildTimeConfig.virtual;
if (startVirtual) {
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 4b7b13dfbc37aa..69568666ea191e 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
@@ -35,6 +35,7 @@
import io.quarkus.runtime.Timing;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.configuration.ConfigInstantiator;
+import io.quarkus.runtime.configuration.MemorySize;
import io.quarkus.vertx.core.runtime.VertxCoreRecorder;
import io.quarkus.vertx.core.runtime.config.VertxConfiguration;
import io.quarkus.vertx.http.runtime.filters.Filter;
@@ -61,6 +62,7 @@
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.BodyHandler;
@Recorder
public class VertxHttpRecorder {
@@ -169,7 +171,8 @@ public void startServer(RuntimeValue vertxRuntimeValue, ShutdownContext s
public void finalizeRouter(BeanContainer container, Consumer defaultRouteHandler,
List filterList, RuntimeValue vertx,
- RuntimeValue runtimeValue, String rootPath, LaunchMode launchMode) {
+ RuntimeValue runtimeValue, String rootPath, LaunchMode launchMode, boolean requireBodyHandler,
+ Handler bodyHandler) {
// install the default route at the end
Router router = runtimeValue.getValue();
@@ -200,6 +203,18 @@ public void finalizeRouter(BeanContainer container, Consumer defaultRoute
container.instance(RouterProducer.class).initialize(resumingRouter);
router.route().last().failureHandler(new QuarkusErrorHandler(launchMode.isDevOrTest()));
+ if (requireBodyHandler) {
+ //if this is set then everything needs the body handler installed
+ //TODO: config etc
+ router.route().order(Integer.MIN_VALUE).handler(new Handler() {
+ @Override
+ public void handle(RoutingContext routingContext) {
+ routingContext.request().resume();
+ bodyHandler.handle(routingContext);
+ }
+ });
+ }
+
if (rootPath.equals("/")) {
if (hotReplacementHandler != null) {
router.route().order(-1).handler(hotReplacementHandler);
@@ -626,4 +641,24 @@ public static Handler getRootHandler() {
return ACTUAL_ROOT;
}
+ public Handler createBodyHandler(HttpConfiguration httpConfiguration) {
+ BodyHandler bodyHandler = BodyHandler.create();
+ Optional maxBodySize = httpConfiguration.limits.maxBodySize;
+ if (maxBodySize.isPresent()) {
+ bodyHandler.setBodyLimit(maxBodySize.get().asLongValue());
+ }
+ final BodyConfig bodyConfig = httpConfiguration.body;
+ bodyHandler.setHandleFileUploads(bodyConfig.handleFileUploads);
+ bodyHandler.setUploadsDirectory(bodyConfig.uploadsDirectory);
+ bodyHandler.setDeleteUploadedFilesOnEnd(bodyConfig.deleteUploadedFilesOnEnd);
+ bodyHandler.setMergeFormAttributes(bodyConfig.mergeFormAttributes);
+ bodyHandler.setPreallocateBodyBuffer(bodyConfig.preallocateBodyBuffer);
+ return new Handler() {
+ @Override
+ public void handle(RoutingContext event) {
+ event.request().resume();
+ bodyHandler.handle(event);
+ }
+ };
+ }
}
diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxInputStream.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxInputStream.java
index 00cd2a23063863..357f77de923aac 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxInputStream.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxInputStream.java
@@ -81,7 +81,7 @@ public int available() throws IOException {
if (finished) {
return -1;
}
-
+
return exchange.readBytesAvailable();
}
@@ -201,13 +201,13 @@ public int readBytesAvailable() {
if (input1 != null) {
return input1.getByteBuf().readableBytes();
}
-
+
String length = request.getHeader(HttpHeaders.CONTENT_LENGTH);
-
+
if (length == null) {
return 0;
}
-
+
return Integer.parseInt(length);
}
}
diff --git a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/BodyHandlerBuildItem.java b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/BodyHandlerBuildItem.java
index 715dbafcde91bb..d8e3e968eef7ba 100644
--- a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/BodyHandlerBuildItem.java
+++ b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/BodyHandlerBuildItem.java
@@ -4,6 +4,10 @@
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
+/**
+ * use {@link io.quarkus.vertx.http.deployment.BodyHandlerBuildItem} instead
+ */
+@Deprecated
public final class BodyHandlerBuildItem extends SimpleBuildItem {
private final Handler handler;
diff --git a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
index 8b98af3df949c8..ed69c72f5731eb 100644
--- a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
+++ b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java
@@ -48,9 +48,9 @@
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.vertx.http.deployment.FilterBuildItem;
+import io.quarkus.vertx.http.deployment.RequireBodyHandlerBuildItem;
import io.quarkus.vertx.http.deployment.RouteBuildItem;
import io.quarkus.vertx.http.runtime.HandlerType;
-import io.quarkus.vertx.http.runtime.HttpConfiguration;
import io.quarkus.vertx.web.Route;
import io.quarkus.vertx.web.RouteBase;
import io.quarkus.vertx.web.RouteFilter;
@@ -149,9 +149,8 @@ void validateBeanDeployment(
}
@BuildStep
- @Record(ExecutionTime.RUNTIME_INIT)
- BodyHandlerBuildItem bodyHandler(VertxWebRecorder recorder, HttpConfiguration httpConfiguration) {
- return new BodyHandlerBuildItem(recorder.createBodyHandler(httpConfiguration));
+ BodyHandlerBuildItem bodyHandler(io.quarkus.vertx.http.deployment.BodyHandlerBuildItem realOne) {
+ return new BodyHandlerBuildItem(realOne.getHandler());
}
@BuildStep
@@ -163,9 +162,10 @@ void addAdditionalRoutes(
BuildProducer generatedClass,
AnnotationProxyBuildItem annotationProxy,
BuildProducer reflectiveClasses,
- BodyHandlerBuildItem bodyHandler,
+ io.quarkus.vertx.http.deployment.BodyHandlerBuildItem bodyHandler,
BuildProducer routeProducer,
- BuildProducer filterProducer) throws IOException {
+ BuildProducer filterProducer,
+ List bodyHandlerRequired) throws IOException {
ClassOutput classOutput = new GeneratedClassGizmoAdaptor(generatedClass, true);
diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
index ffc08969aa4fb1..e7b3051717b6b5 100644
--- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
+++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/VertxWebRecorder.java
@@ -1,20 +1,15 @@
package io.quarkus.vertx.web.runtime;
import java.lang.reflect.InvocationTargetException;
-import java.util.Optional;
import java.util.function.Function;
import io.quarkus.runtime.annotations.Recorder;
-import io.quarkus.runtime.configuration.MemorySize;
-import io.quarkus.vertx.http.runtime.BodyConfig;
-import io.quarkus.vertx.http.runtime.HttpConfiguration;
import io.quarkus.vertx.http.runtime.RouterProducer;
import io.quarkus.vertx.web.Route;
import io.vertx.core.Handler;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
-import io.vertx.ext.web.handler.BodyHandler;
@Recorder
public class VertxWebRecorder {
@@ -66,33 +61,14 @@ public io.vertx.ext.web.Route apply(Router router) {
route.consumes(consumes);
}
}
- route.handler(bodyHandler);
+ if (bodyHandler != null) {
+ route.handler(bodyHandler);
+ }
return route;
}
};
}
- public Handler createBodyHandler(HttpConfiguration httpConfiguration) {
- BodyHandler bodyHandler = BodyHandler.create();
- Optional maxBodySize = httpConfiguration.limits.maxBodySize;
- if (maxBodySize.isPresent()) {
- bodyHandler.setBodyLimit(maxBodySize.get().asLongValue());
- }
- final BodyConfig bodyConfig = httpConfiguration.body;
- bodyHandler.setHandleFileUploads(bodyConfig.handleFileUploads);
- bodyHandler.setUploadsDirectory(bodyConfig.uploadsDirectory);
- bodyHandler.setDeleteUploadedFilesOnEnd(bodyConfig.deleteUploadedFilesOnEnd);
- bodyHandler.setMergeFormAttributes(bodyConfig.mergeFormAttributes);
- bodyHandler.setPreallocateBodyBuffer(bodyConfig.preallocateBodyBuffer);
- return new Handler() {
- @Override
- public void handle(RoutingContext event) {
- event.request().resume();
- bodyHandler.handle(event);
- }
- };
- }
-
private String ensureStartWithSlash(String path) {
if (path.startsWith("/")) {
return path;