Skip to content

Commit

Permalink
Add a RESTEasy Multipart extension
Browse files Browse the repository at this point in the history
  • Loading branch information
gsmet committed Sep 4, 2020
1 parent 09c9e80 commit 175d966
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 0 deletions.
10 changes: 10 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,16 @@
<artifactId>quarkus-resteasy-jaxb-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-multipart</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-multipart-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-server-common</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public enum Feature {
RESTEASY_JACKSON,
RESTEASY_JAXB,
RESTEASY_JSONB,
RESTEASY_MULTIPART,
RESTEASY_MUTINY,
RESTEASY_QUTE,
REST_CLIENT,
Expand Down
1 change: 1 addition & 0 deletions extensions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<module>resteasy-jaxb</module>
<module>resteasy-mutiny</module>
<module>resteasy-qute</module>
<module>resteasy-multipart</module>
<module>rest-client</module>
<module>rest-client-jackson</module>
<module>rest-client-jsonb</module>
Expand Down
54 changes: 54 additions & 0 deletions extensions/resteasy-multipart/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-resteasy-multipart-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-resteasy-multipart-deployment</artifactId>
<name>Quarkus - RESTEasy - Multipart - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-multipart</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.quarkus.resteasy.multipart.deployment;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.processor.DotNames;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.resteasy.multipart.runtime.MultipartInputPartConfigContainerRequestFilter;

public class ResteasyMultipartProcessor {

@BuildStep
void feature(BuildProducer<FeatureBuildItem> feature) {
feature.produce(new FeatureBuildItem(Feature.RESTEASY_MULTIPART));
}

@BuildStep
AdditionalBeanBuildItem filter() {
return new AdditionalBeanBuildItem.Builder()
.addBeanClass(MultipartInputPartConfigContainerRequestFilter.class)
.setUnremovable()
.setDefaultScope(DotNames.SINGLETON)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.resteasy.multipart;

import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;

import org.jboss.resteasy.annotations.providers.multipart.PartType;

public class FeedbackBody {

private byte[] file;

@FormParam("fileName")
@PartType(MediaType.TEXT_PLAIN)
public String fileName;

@FormParam("content")
@PartType(MediaType.TEXT_PLAIN)
public String content;

public byte[] getFile() {
return file;
}

@FormParam("file")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
public void setFile(byte[] file) {
this.file = file;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.quarkus.resteasy.multipart;

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;

import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;

@Path("/test")
public class FeedbackResource {

@POST
@Path("/multipart-encoding")
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String postForm(@MultipartForm final FeedbackBody feedback) {
return feedback.content;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkus.resteasy.multipart;

import static org.hamcrest.CoreMatchers.is;

import java.io.File;
import java.net.URISyntaxException;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
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;
import io.restassured.RestAssured;
import io.restassured.http.Header;

public class MultipartEncodingTest {

private static final String TEXT_WITH_ACCENTED_CHARACTERS = "Text with UTF-8 accented characters: é à è";
private static final String TEXT_FILE = "test-multipart.txt";

@RegisterExtension
static QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(FeedbackBody.class, FeedbackResource.class)
.add(new StringAsset("Content of the file"), TEXT_FILE));

@Test
public void testMultipartEncoding() throws URISyntaxException {
RestAssured
.given()
.header(new Header("content-type", "multipart/form-data"))
.multiPart("file",
new File(Thread.currentThread().getContextClassLoader().getResource(TEXT_FILE).toURI()))
.formParam("fileName", "test-multipart.txt")
.formParam("content", TEXT_WITH_ACCENTED_CHARACTERS)
.post("/test/multipart-encoding")
.then()
.statusCode(200)
.body(is(TEXT_WITH_ACCENTED_CHARACTERS));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Content of the file
20 changes: 20 additions & 0 deletions extensions/resteasy-multipart/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-build-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../../build-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-resteasy-multipart-parent</artifactId>
<name>Quarkus - RESTEasy - Multipart</name>
<packaging>pom</packaging>
<modules>
<module>deployment</module>
<module>runtime</module>
</modules>
</project>
57 changes: 57 additions & 0 deletions extensions/resteasy-multipart/runtime/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-resteasy-multipart-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-resteasy-multipart</artifactId>
<name>Quarkus - RESTEasy - Multipart - Runtime</name>
<description>Multipart support for RESTEasy</description>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.resteasy.multipart.runtime;

import java.io.IOException;

import javax.annotation.Priority;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.ext.Provider;

import org.jboss.resteasy.plugins.providers.multipart.InputPart;

import io.quarkus.arc.WithCaching;

@Provider
@Priority(Priorities.HEADER_DECORATOR)
public class MultipartInputPartConfigContainerRequestFilter implements ContainerRequestFilter {

@WithCaching
@Inject
Instance<ResteasyMultipartRuntimeConfig> resteasyMultipartConfigInstance;

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
ResteasyMultipartRuntimeConfig resteasyMultipartConfig = resteasyMultipartConfigInstance.get();

requestContext.setProperty(InputPart.DEFAULT_CHARSET_PROPERTY,
resteasyMultipartConfig.inputPart.defaultCharset.name());
requestContext.setProperty(InputPart.DEFAULT_CONTENT_TYPE_PROPERTY,
resteasyMultipartConfig.inputPart.defaultContentType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.resteasy.multipart.runtime;

import java.nio.charset.Charset;

import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;

@ConfigRoot(phase = ConfigPhase.RUN_TIME)
public class ResteasyMultipartRuntimeConfig {

/**
* Input part configuration.
*/
@ConfigItem
public InputPartConfigGroup inputPart;

@ConfigGroup
public static class InputPartConfigGroup {

/**
* Default charset.
* <p>
* Note that the default value is UTF-8 which is different from RESTEasy's default value.
*/
@ConfigItem(defaultValue = "UTF-8")
public Charset defaultCharset;

/**
* The default content-type.
*/
@ConfigItem(defaultValue = "text/plain")
public String defaultContentType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: "RESTEasy Multipart"
metadata:
keywords:
- "resteasy-multipart"
- "multipart"
- "upload"
- "resteasy"
- "jaxrs"
categories:
- "web"
status: "stable"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.resteasy.multipart.runtime.MultipartInputPartConfigContainerRequestFilter

0 comments on commit 175d966

Please sign in to comment.