|
1 | 1 | # Quarkus - OpenAPI Generator |
2 | 2 |
|
3 | 3 | <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> |
4 | | -[](#contributors-) |
| 4 | +[](#contributors-) |
5 | 5 | <!-- ALL-CONTRIBUTORS-BADGE:END --> |
6 | 6 |
|
7 | 7 | Quarkus' extension for generation of [Rest Clients](https://quarkus.io/guides/rest-client) based on OpenAPI specification files. |
@@ -276,6 +276,69 @@ org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/failureRatio=3.14 |
276 | 276 | org.acme.openapi.simple.api.DefaultApi/byeGet/CircuitBreaker/successThreshold=22 |
277 | 277 | ```` |
278 | 278 |
|
| 279 | +## Sending multipart/form-data |
| 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 generated default 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 | + |
279 | 342 | ## Generating files via InputStream |
280 | 343 |
|
281 | 344 | 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` |
@@ -304,10 +367,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d |
304 | 367 | <table> |
305 | 368 | <tr> |
306 | 369 | <td align="center"><a href="https://ricardozanini.medium.com/"><img src="https://avatars.githubusercontent.com/u/1538000?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ricardo Zanini</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=ricardozanini" title="Code">💻</a> <a href="#maintenance-ricardozanini" title="Maintenance">🚧</a></td> |
307 | | - <td align="center"><a href="http://thegreatapi.com"><img src="https://avatars.githubusercontent.com/u/11776454?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Helber Belmiro</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=hbelmiro" title="Documentation">📖</a></td> |
| 370 | + <td align="center"><a href="http://thegreatapi.com"><img src="https://avatars.githubusercontent.com/u/11776454?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Helber Belmiro</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=hbelmiro" title="Documentation">📖</a> <a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=hbelmiro" title="Code">💻</a></td> |
308 | 371 | <td align="center"><a href="http://gastaldi.wordpress.com"><img src="https://avatars.githubusercontent.com/u/54133?v=4?s=100" width="100px;" alt=""/><br /><sub><b>George Gastaldi</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=gastaldi" title="Code">💻</a> <a href="#infra-gastaldi" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td> |
309 | 372 | <td align="center"><a href="https://github.com/RishiKumarRay"><img src="https://avatars.githubusercontent.com/u/87641376?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rishi Kumar Ray</b></sub></a><br /><a href="#infra-RishiKumarRay" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td> |
310 | 373 | <td align="center"><a href="https://github.com/fjtirado"><img src="https://avatars.githubusercontent.com/u/65240126?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Francisco Javier Tirado Sarti</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=fjtirado" title="Code">💻</a></td> |
| 374 | + <td align="center"><a href="https://github.com/Orbifoldt"><img src="https://avatars.githubusercontent.com/u/30009459?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Orbifoldt</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-openapi-generator/commits?author=Orbifoldt" title="Code">💻</a></td> |
311 | 375 | </tr> |
312 | 376 | </table> |
313 | 377 |
|
|
0 commit comments