Skip to content

Commit 8944896

Browse files
committed
Adding info on multipart/form-data to readme
1 parent 5bd77be commit 8944896

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,69 @@ org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/failureRatio=3.14
276276
org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/successThreshold=22
277277
````
278278

279+
## Multipart/form-data input
280+
The rest client also supports request with mime-type multipart/form-data and, if the schema of the request body is known in advance, we can also automatically generate the models of the request bodies.
281+
282+
You need to add the following additional dependency to your `pom.xml`:
283+
```xml
284+
<dependency>
285+
<groupId>io.quarkus</groupId>
286+
<artifactId>quarkus-resteasy-multipart</artifactId>
287+
</dependency>
288+
```
289+
For any multipart/form-data operation a model for the request body will be generated. Each part of the multipart is a field in this model that is annotated with the following annotations:
290+
- `javax.ws.rs.FormParam`, where the value parameter denotes the part name,
291+
- `org.jboss.resteasy.annotations.providers.multipart.PartType`, where the parameter is the jax-rs MediaType of the part (see below for details),
292+
- and, if the part contains a file, `org.jboss.resteasy.annotations.providers.multipart.PartFilename`, with a default generate value parameter that will be passed as the fileName sub-header in the Content-Disposition header of the part.
293+
294+
For example, the model for a request that requires a file, a string and some complex object will look like this:
295+
```java
296+
public class MultipartBody {
297+
298+
@FormParam("file")
299+
@PartType(MediaType.APPLICATION_OCTET_STREAM)
300+
@PartFilename("defaultFileName")
301+
public File file;
302+
303+
@FormParam("fileName")
304+
@PartType(MediaType.TEXT_PLAIN)
305+
public String fileName;
306+
307+
@FormParam("someObject")
308+
@PartType(MediaType.APPLICATION_JSON)
309+
public MyComplexObject someObject;
310+
}
311+
```
312+
313+
Then in the client the `org.jboss.resteasy.annotations.providers.multipart.MultipartForm` annotation is added in front of the multipart parameter:
314+
```java
315+
@Path("/echo")
316+
@RegisterRestClient
317+
public interface MultipartService {
318+
319+
@POST
320+
@Consumes(MediaType.MULTIPART_FORM_DATA)
321+
@Produces(MediaType.TEXT_PLAIN)
322+
String sendMultipartData(@MultipartForm MultipartBody data);
323+
324+
}
325+
```
326+
See [Quarkus - Using the REST Client with Multipart](https://quarkus.io/guides/rest-client-multipart) and the [RESTEasy JAX-RS specifications](https://docs.jboss.org/resteasy/docs/4.7.5.Final/userguide/html_single/index.html) for more details.
327+
328+
Importantly, if some multipart request bodies contain complex objects (i.e. non-primitives) you need to explicitly tell the Open API generator to create models for these objects by setting the `skip-form-model` property corresponding to your spec in the `application.properties` to `false`, e.g.:
329+
```properties
330+
quarkus.openapi-generator.codegen.spec."my-multipart-requests.yml".skip-form-model=false
331+
```
332+
333+
### Default content-types according to OpenAPI Specification and limitations
334+
The [OAS 3.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#special-considerations-for-multipart-content) specifies the following default content-types for a multipart:
335+
- If the property is a primitive, or an array of primitive values, the default Content-Type is `text/plain`
336+
- If the property is complex, or an array of complex values, the default Content-Type is `application/json`
337+
- If the property is a `type: string` with `format: binary` or `format: base64` (aka a file object), the default Content-Type is `application/octet-stream`
338+
339+
A different content-type may be defined in your api spec, but this is not yet supported in the code generation. Also, this "annotation-oriented" approach of RestEasy (i.e. using `@MultipartForm` to denote the multipart body parameter) does not seem to properly support the unmarshalling of arrays of the same type (e.g. array of files), in these cases it uses Content-Type equal to `application/json`.
340+
341+
279342
## Generating files via InputStream
280343

281344
Having the files in the `src/main/openapi` directory will generate the REST stubs by default. Alternatively, you can implement the `io.quarkiverse.openapi.generator.codegen.OpenApiSpecInputProvider`

integration-tests/src/main/resources/application.properties

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,4 @@ org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/successThreshold =
2424

2525
quarkus.openapi-generator.codegen.spec."multipart-requests.yml".base-package=org.acme.openapi.multipart
2626
# By default the openapi-generator doesn't generate models for multipart requests
27-
quarkus.openapi-generator.codegen.spec."multipart-requests.yml".skip-form-model=false
28-
quarkus.log.category."org.apache.http".level=DEBUG
27+
quarkus.openapi-generator.codegen.spec."multipart-requests.yml".skip-form-model=false

0 commit comments

Comments
 (0)