Skip to content

Commit

Permalink
Do multipart parsing inside RR
Browse files Browse the repository at this point in the history
This gives us a lot more flexibility, and allows it to work
with multiple backends.

Fixes quarkusio#17430
  • Loading branch information
stuartwdouglas committed Jun 8, 2021
1 parent 96a1a52 commit 983d4b3
Show file tree
Hide file tree
Showing 26 changed files with 2,038 additions and 478 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
Expand Down Expand Up @@ -227,26 +226,6 @@ public void closeConnection() {
context.response().close();
}

@Override
public String getFormAttribute(String name) {
if (context.queryParams().contains(name)) {
return null;
}
return request.getParameter(name);
}

@Override
public List<String> getAllFormAttributes(String name) {
if (context.queryParams().contains(name)) {
return Collections.emptyList();
}
String[] values = request.getParameterValues(name);
if (values == null) {
return Collections.emptyList();
}
return Arrays.asList(values);
}

@Override
public String getQueryParam(String name) {
if (!context.queryParams().contains(name)) {
Expand Down Expand Up @@ -275,12 +254,6 @@ public boolean isRequestEnded() {
return context.request().isEnded();
}

@Override
public void setExpectMultipart(boolean expectMultipart) {
//read the form data
request.getParameterMap();
}

@Override
public InputStream createInputStream(ByteBuffer existingData) {
return new ServletResteasyReactiveInputStream(existingData, request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.jboss.resteasy.reactive.common.util.DeploymentUtils;
import org.jboss.resteasy.reactive.common.util.types.TypeSignatureParser;
import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
import org.jboss.resteasy.reactive.server.core.multipart.DefaultFileUpload;
import org.jboss.resteasy.reactive.server.injection.ResteasyReactiveInjectionContext;
import org.jboss.resteasy.reactive.server.spi.ServerHttpRequest;

Expand All @@ -39,7 +40,6 @@
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.resteasy.reactive.server.runtime.multipart.MultipartSupport;
import io.quarkus.resteasy.reactive.server.runtime.multipart.QuarkusFileUpload;

final class MultipartPopulatorGenerator {

Expand Down Expand Up @@ -273,7 +273,7 @@ static String generate(ClassInfo multipartClassInfo, ClassOutput classOutput, In
// uploaded file are present in the RoutingContext and are extracted using MultipartSupport#getFileUpload

ResultHandle fileUploadHandle = populate.invokeStaticMethod(
MethodDescriptor.ofMethod(MultipartSupport.class, "getFileUpload", QuarkusFileUpload.class,
MethodDescriptor.ofMethod(MultipartSupport.class, "getFileUpload", DefaultFileUpload.class,
String.class, ResteasyReactiveRequestContext.class),
formAttrNameHandle, rrCtxHandle);
if (fieldDotName.equals(DotNames.FIELD_UPLOAD_NAME)) {
Expand All @@ -285,7 +285,7 @@ static String generate(ClassInfo multipartClassInfo, ClassOutput classOutput, In
fileUploadNullTrue.breakScope();
BytecodeCreator fileUploadFalse = fileUploadNullBranch.falseBranch();
ResultHandle pathHandle = fileUploadFalse.invokeVirtualMethod(
MethodDescriptor.ofMethod(QuarkusFileUpload.class, "uploadedFile", Path.class),
MethodDescriptor.ofMethod(DefaultFileUpload.class, "uploadedFile", Path.class),
fileUploadHandle);
if (fieldDotName.equals(DotNames.PATH_NAME)) {
fileUploadFalse.assign(resultHandle, pathHandle);
Expand Down Expand Up @@ -348,9 +348,10 @@ static String generate(ClassInfo multipartClassInfo, ClassOutput classOutput, In
// in this case all we need to do is read the value of the form attribute

populate.assign(resultHandle,
populate.invokeInterfaceMethod(MethodDescriptor.ofMethod(ServerHttpRequest.class,
"getFormAttribute", String.class, String.class), serverReqHandle,
formAttrNameHandle));
populate.invokeVirtualMethod(MethodDescriptor.ofMethod(ResteasyReactiveRequestContext.class,
"getFormParameter", Object.class, String.class, boolean.class, boolean.class),
rrCtxHandle,
formAttrNameHandle, populate.load(true), populate.load(false)));
} else {
// we need to use the field type and the media type to locate a MessageBodyReader

Expand Down Expand Up @@ -382,11 +383,11 @@ static String generate(ClassInfo multipartClassInfo, ClassOutput classOutput, In
MethodDescriptor.ofMethod(MediaType.class, "valueOf", MediaType.class, String.class),
clinit.load(partType)));

ResultHandle formStrValueHandle = populate.invokeInterfaceMethod(
MethodDescriptor.ofMethod(ServerHttpRequest.class,
"getFormAttribute", String.class, String.class),
serverReqHandle,
formAttrNameHandle);
ResultHandle formStrValueHandle = populate.invokeVirtualMethod(
MethodDescriptor.ofMethod(ResteasyReactiveRequestContext.class,
"getFormParameter", Object.class, String.class, boolean.class, boolean.class),
rrCtxHandle,
formAttrNameHandle, populate.load(true), populate.load(false));

populate.assign(resultHandle, populate.invokeStaticMethod(
MethodDescriptor.ofMethod(MultipartSupport.class, "convertFormAttribute", Object.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem;
Expand Down Expand Up @@ -274,7 +275,8 @@ public void setupEndpoints(Capabilities capabilities, BeanArchiveIndexBuildItem
ParamConverterProvidersBuildItem paramConverterProvidersBuildItem,
ContextResolversBuildItem contextResolversBuildItem,
List<ApplicationClassPredicateBuildItem> applicationClassPredicateBuildItems,
List<MethodScannerBuildItem> methodScanners, ResteasyReactiveServerConfig serverConfig)
List<MethodScannerBuildItem> methodScanners, ResteasyReactiveServerConfig serverConfig,
LaunchModeBuildItem launchModeBuildItem)
throws NoSuchMethodException {

if (!resourceScanningResultBuildItem.isPresent()) {
Expand Down Expand Up @@ -549,7 +551,7 @@ private boolean hasAnnotation(MethodInfo method, short paramPosition, DotName an
RuntimeValue<Deployment> deployment = recorder.createDeployment(deploymentInfo,
beanContainerBuildItem.getValue(), shutdownContext, vertxConfig,
requestContextFactoryBuildItem.map(RequestContextFactoryBuildItem::getFactory).orElse(null),
initClassFactory);
initClassFactory, launchModeBuildItem.getLaunchMode());

quarkusRestDeploymentBuildItemBuildProducer
.produce(new ResteasyReactiveDeploymentBuildItem(deployment, deploymentPath));
Expand Down
Loading

0 comments on commit 983d4b3

Please sign in to comment.