From aafbbf55548797a13de45e4b8fb25ba663fa54fe Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Mon, 16 Aug 2021 10:16:32 +1000 Subject: [PATCH] Fix handling multipart requests manually Fixes #19404 --- .../common/processor/EndpointIndexer.java | 9 ++++- .../reactive/common/model/ResourceReader.java | 3 +- .../framework/ResteasyReactiveUnitTest.java | 26 +++++++++++++- .../vertx/test/multipart/EchoResource.java | 21 ++++++++++++ .../test/multipart/RawMultipartTestCase.java | 34 +++++++++++++++++++ 5 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/EchoResource.java create mode 100644 independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/RawMultipartTestCase.java diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index 28c5b5343a772..e1a8f4d6eb5bd 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -958,7 +958,14 @@ && isContextType(paramType.asClassType())) { // in this case it is safe to assume that we are consuming multipart data // we already don't allow multipart to be used along with body in the same method, // so this is completely safe - builder.setType(ParameterType.MULTI_PART_FORM); + var type = toClassName(paramType, currentClassInfo, actualEndpointInfo, index); + var typeInfo = index.getClassByName(DotName.createSimple(type)); + if (typeInfo != null && typeInfo.annotations().containsKey(REST_FORM_PARAM)) { + builder.setType(ParameterType.MULTI_PART_FORM); + } else { + //if the paramater does not have @RestForm annotations we treat it as a normal body + builder.setType(ParameterType.BODY); + } } else { builder.setType(ParameterType.BODY); } diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java index 97d176658f425..f0caa580ad710 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java @@ -21,8 +21,9 @@ public class ResourceReader { private volatile List mediaTypes; private volatile MessageBodyReader instance; - public void setFactory(BeanFactory> factory) { + public ResourceReader setFactory(BeanFactory> factory) { this.factory = factory; + return this; } public BeanFactory> getFactory() { diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/framework/ResteasyReactiveUnitTest.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/framework/ResteasyReactiveUnitTest.java index 10f075bb74cff..419c5eebbc962 100644 --- a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/framework/ResteasyReactiveUnitTest.java +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/framework/ResteasyReactiveUnitTest.java @@ -31,12 +31,14 @@ import java.util.logging.Logger; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.jboss.resteasy.reactive.common.ResteasyReactiveConfig; import org.jboss.resteasy.reactive.common.model.ResourceClass; +import org.jboss.resteasy.reactive.common.model.ResourceReader; import org.jboss.resteasy.reactive.common.model.ResourceWriter; import org.jboss.resteasy.reactive.common.processor.JandexUtil; import org.jboss.resteasy.reactive.common.processor.scanning.ApplicationScanningResult; @@ -46,6 +48,7 @@ import org.jboss.resteasy.reactive.server.core.Deployment; import org.jboss.resteasy.reactive.server.core.DeploymentInfo; import org.jboss.resteasy.reactive.server.core.ServerSerialisers; +import org.jboss.resteasy.reactive.server.core.startup.CustomServerRestHandlers; import org.jboss.resteasy.reactive.server.core.startup.RuntimeDeploymentManager; import org.jboss.resteasy.reactive.server.handlers.RestInitialHandler; import org.jboss.resteasy.reactive.server.processor.ServerEndpointIndexer; @@ -53,6 +56,7 @@ import org.jboss.resteasy.reactive.server.processor.scanning.ResteasyReactiveExceptionMappingScanner; import org.jboss.resteasy.reactive.server.processor.scanning.ResteasyReactiveFeatureScanner; import org.jboss.resteasy.reactive.server.processor.scanning.ResteasyReactiveParamConverterScanner; +import org.jboss.resteasy.reactive.server.providers.serialisers.ServerByteArrayMessageBodyHandler; import org.jboss.resteasy.reactive.server.providers.serialisers.ServerStringMessageBodyHandler; import org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler; import org.jboss.resteasy.reactive.server.vertx.VertxRequestContextFactory; @@ -248,12 +252,31 @@ public MessageBodyWriter getInstance() { @Override public void close() { + } + }; + } + })); + serialisers.addReader(byte[].class, new ResourceReader() + .setMediaTypeStrings(Collections.singletonList(MediaType.WILDCARD)) + .setFactory(new BeanFactory>() { + @Override + public BeanInstance> createInstance() { + return new BeanInstance>() { + @Override + public MessageBodyReader getInstance() { + return new ServerByteArrayMessageBodyHandler(); + } + + @Override + public void close() { + } }; } })); DeploymentInfo info = new DeploymentInfo() .setApplicationPath("/") + .setConfig(new ResteasyReactiveConfig()) .setFeatures(ResteasyReactiveFeatureScanner.createFeatures(index, applicationScanningResult)) .setInterceptors( ResteasyReactiveInterceptorScanner.createResourceInterceptors(index, applicationScanningResult)) @@ -284,7 +307,8 @@ public Application get() { } } }); - RuntimeDeploymentManager runtimeDeploymentManager = new RuntimeDeploymentManager(info, () -> executor, null, + RuntimeDeploymentManager runtimeDeploymentManager = new RuntimeDeploymentManager(info, () -> executor, + new CustomServerRestHandlers(null), closeable -> closeTasks.add(closeable), new VertxRequestContextFactory(), ThreadSetupAction.NOOP, "/"); Deployment deployment = runtimeDeploymentManager.deploy(); RestInitialHandler initialHandler = new RestInitialHandler(deployment); diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/EchoResource.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/EchoResource.java new file mode 100644 index 0000000000000..fdcb847ca4d20 --- /dev/null +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/EchoResource.java @@ -0,0 +1,21 @@ +package org.jboss.resteasy.reactive.server.vertx.test.multipart; + +import io.smallrye.common.annotation.NonBlocking; +import java.nio.charset.StandardCharsets; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/echo") +public class EchoResource { + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.TEXT_PLAIN) + @NonBlocking + public String echo(byte[] request) { + return new String(request, StandardCharsets.UTF_8); + } +} diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/RawMultipartTestCase.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/RawMultipartTestCase.java new file mode 100644 index 0000000000000..0218c5f1b68c9 --- /dev/null +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/multipart/RawMultipartTestCase.java @@ -0,0 +1,34 @@ +package org.jboss.resteasy.reactive.server.vertx.test.multipart; + +import io.restassured.RestAssured; +import java.util.function.Supplier; +import org.hamcrest.Matchers; +import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RawMultipartTestCase { + + @RegisterExtension + static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest() + .setArchiveProducer(new Supplier() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class).addClass(EchoResource.class); + } + }); + + @Test + public void testHelloEndpoint() { + RestAssured.given() + .when() + .multiPart("testName", "testValue") + .post("/echo") + .then() + .statusCode(200) + .body(Matchers.containsString("testValue")); + } + +}