From b3a9aa735f68763dbe0f15ed522c8045157f946d Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Fri, 16 Feb 2024 08:47:43 +0200 Subject: [PATCH] Expand types which are considered text in multipart handling Fixes: #38802 --- .../MultipartTextWithoutFilenameTest.java | 52 +++++++++++++++++++ .../reactive/common/util/MediaTypeHelper.java | 8 +-- .../server/core/EncodedMediaType.java | 9 +--- .../multipart/MultiPartParserDefinition.java | 3 +- 4 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/multipart/MultipartTextWithoutFilenameTest.java diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/multipart/MultipartTextWithoutFilenameTest.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/multipart/MultipartTextWithoutFilenameTest.java new file mode 100644 index 0000000000000..c774985eaf5fb --- /dev/null +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/multipart/MultipartTextWithoutFilenameTest.java @@ -0,0 +1,52 @@ +package io.quarkus.resteasy.reactive.server.test.multipart; + +import static io.restassured.RestAssured.given; + +import java.io.IOException; +import java.util.function.Supplier; + +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; + +import org.jboss.resteasy.reactive.RestResponse; +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; + +import io.quarkus.test.QuarkusUnitTest; + +public class MultipartTextWithoutFilenameTest { + + @RegisterExtension + static QuarkusUnitTest test = new QuarkusUnitTest() + .setArchiveProducer(new Supplier<>() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(Resource.class); + } + }); + + @Test + public void test() throws IOException { + given() + .contentType("multipart/form-data") + .multiPart("firstParam", "{\"id\":\"myId\",\"name\":\"myName\"}", "application/json") + .when() + .post("/test") + .then() + .statusCode(200); + } + + @Path("/test") + public static class Resource { + + @POST + public RestResponse testMultipart(@FormParam("firstParam") final String firstParam, + @FormParam("secondParam") final String secondParam) { + return RestResponse.ok(); + } + } +} diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java index 81cedd7b62c60..ce799d31a24d6 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java @@ -267,10 +267,12 @@ public static boolean equivalentParams(MediaType m1, MediaType m2) { return true; } + // TODO: does this need to be more complex? public static boolean isTextLike(MediaType mediaType) { - return "text".equalsIgnoreCase(mediaType.getType()) - || ("application".equalsIgnoreCase(mediaType.getType()) - && mediaType.getSubtype().toLowerCase().startsWith("xml")); + String type = mediaType.getType(); + String subtype = mediaType.getSubtype(); + return (type.equals("application") && (subtype.contains("json") || subtype.contains("xml") || subtype.contains("yaml"))) + || type.equals("text"); } public static boolean isUnsupportedWildcardSubtype(MediaType mediaType) { diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/EncodedMediaType.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/EncodedMediaType.java index c219865d5efa8..1c3c4310be4c9 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/EncodedMediaType.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/EncodedMediaType.java @@ -5,6 +5,7 @@ import jakarta.ws.rs.core.MediaType; +import org.jboss.resteasy.reactive.common.util.MediaTypeHelper; import org.jboss.resteasy.reactive.server.spi.ContentType; /** @@ -21,7 +22,7 @@ public EncodedMediaType(MediaType mediaType) { MediaType effectiveMediaType = mediaType; String effectiveCharset; String originalCharset = mediaType.getParameters().get("charset"); - if (isStringMediaType(mediaType)) { + if (MediaTypeHelper.isTextLike(mediaType)) { effectiveCharset = originalCharset; if (effectiveCharset == null) { effectiveCharset = StandardCharsets.UTF_8.name(); @@ -38,12 +39,6 @@ public EncodedMediaType(MediaType mediaType) { } // TODO: does this need to be more complex? - private boolean isStringMediaType(MediaType mediaType) { - String type = mediaType.getType(); - String subtype = mediaType.getSubtype(); - return (type.equals("application") && (subtype.contains("json") || subtype.contains("xml") || subtype.contains("yaml"))) - || type.equals("text"); - } @Override public String toString() { diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/multipart/MultiPartParserDefinition.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/multipart/MultiPartParserDefinition.java index 42ed5899e7356..1cea966a9e0b1 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/multipart/MultiPartParserDefinition.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/multipart/MultiPartParserDefinition.java @@ -29,6 +29,7 @@ import org.jboss.logging.Logger; import org.jboss.resteasy.reactive.common.headers.HeaderUtil; import org.jboss.resteasy.reactive.common.util.CaseInsensitiveMap; +import org.jboss.resteasy.reactive.common.util.MediaTypeHelper; import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext; import org.jboss.resteasy.reactive.server.spi.ServerHttpRequest; @@ -366,7 +367,7 @@ private boolean isText(String contentType) { if (contentType == null || contentType.isEmpty()) { // https://www.rfc-editor.org/rfc/rfc7578.html#section-4.4 says the default content-type if missing is text/plain return true; } - return MediaType.TEXT_PLAIN_TYPE.isCompatible(MediaType.valueOf(contentType)); + return MediaTypeHelper.isTextLike(MediaType.valueOf(contentType)); } public List getCreatedFiles() {