Open stavvy-gkillough opened 1 year ago
I also have this problem:
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"body"
],
"properties": {
"body": {
"allOf": [
{
"$ref": "#/components/schemas/MyRequest"
},
...
]
},
...
}
},
"encoding": {
"body": {
"contentType": "application/json"
}
}
}
}
In the generated API Client Class, no content type is specified, so "text/plain" is used instead of "application/json".
I also can't think of a workaround without adding the generated files to my git repository, which I really want to avoid doing. I tried it on both 6.6.0 and 7.0.1.
Same problem here:
paths:
/fileupload:
post:
description: https://swagger.io/docs/specification/describing-request-body/multipart-requests/
operationId: uploadFiles
tags:
- FileUpload
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
address:
$ref: '#/components/schemas/address'
files:
type: array
items:
type: string
format: binary
encoding:
address:
contentType: application/json
responses:
202:
description: OK
With openapi-generator 7.0.1 the following native client code is generated:
private HttpRequest.Builder uploadFilesRequestBuilder(Address address, List<File> files) throws ApiException {
HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder();
String localVarPath = "/fileupload";
localVarRequestBuilder.uri(URI.create(this.memberVarBaseUri + localVarPath));
localVarRequestBuilder.header("Accept", "application/json");
MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
boolean hasFiles = false;
multiPartBuilder.addTextBody("address", address.toString());
for(int i = 0; i < files.size(); ++i) {
multiPartBuilder.addBinaryBody("files", (File)files.get(i));
hasFiles = true;
}
HttpEntity entity = multiPartBuilder.build();
The encoding part at the address object is missing. It should looks like something like this:
private HttpRequest.Builder uploadFilesRequestBuilder(Address address, List<File> files) throws ApiException
{
HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder();
String localVarPath = "/fileupload";
localVarRequestBuilder.uri(URI.create(this.memberVarBaseUri + localVarPath));
localVarRequestBuilder.header("Accept", "application/json");
MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
boolean hasFiles = false;
try {
multiPartBuilder.addTextBody("address", memberVarObjectMapper.writeValueAsString(address), ContentType.APPLICATION_JSON);
}
catch (JsonProcessingException e) {
throw new ApiException(e);
}
for (int i = 0; i < files.size(); ++i) {
multiPartBuilder.addBinaryBody("files", (File) files.get(i));
hasFiles = true;
}
@ZBSTooling I found a workaround. By using the default library (okhttp-gson), object parts sent in a multipart request have the content type ‘application/json’.
I don’t understand why the native library does not set the content type json for object parts…
Description
The OpenAPI Specification v3 (3.0.0) describes an encoding object for multipart request bodies. The openapi-generator does not honor this in its Java client generation, and instead uses a hard-coded application/octet-stream. I've taken a peek at the generator templates for Java and determined this is indeed hard-coded and could be set dynamically.
Source: v3 encoding-object
This is most important for file-upload use-cases, but should ideally be supported for all form-data parameters.
openapi-generator version
v6.6.0 of the generator (via the openapi-generator-cli)
OpenAPI declaration file content or url
Note: I've stripped my form data down to just the file, but in my actual use-case there are several parameters other than pdfFile.
Steps to reproduce
Using the yaml provided above, observe a request from a generated client does not set the Content-Type header of the individual form data parameters based on the encoding object, but instead uses the hard-coded application/octet-stream. Looking at the generated
ApiClient.java
file'sserialize
method definition reveals the hard-coded value as well.Related issues/PRs
724
1646
Suggest a fix
For all the Java clients, I suggest passing in a
Map<String, String>
with the key being the form param name, and the value being the value found in the encoding object in the yaml. Then useMap.getOrDefault(param.getKey(), MediaType.APPLICATION_OCTET_STREAM_TYPE)
rather than the hard-coded octet stream type.The functional code fix: ApiClient.mustache in the
serialize(...)
method:The following methods would need to pass an additional Map<String, String> to support this change:
ApiClient::invokeAPI
ApiClient::getAPIResponse
The api.mustache template would need to add something like this:
Note: Changing the
serialize
,invokeAPI
, andgetAPIResponse
methods would result in a breaking change ifApiClient
is considered part of the public API of the generated client.