Reputation: 817
I don't really have a ton of experience working with OpenAPI, so hopefully this is an easy one. I have to work with an API that wants a CSV file alongside some identifier as a multipart/form-data request. My OpenAPI spec looks like this:
/api/SomeEndpoint:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
id:
type: string
csv:
type: string
format: binary
encoding:
csv:
contentType: text/csv
I generate the client using the org.openapi.generator:7.11.0
gradle plugin. This works flawlessly, however the generated methods want an actual File
object, which is something I want to get rid of. I'd like to simply pass the data, maybe as a byte[]
. When I alter the OpenAPI spec to format: byte
this also works, but when actually executing the request the Content-Type
header for that part is set to application/json
.
I tried including the encoding
section or adding contentMediaType: text/csv
to the csv
property, but to no avail. It seems like that has no effect whatsoever on the generated client. Does anyone know how to properly configure this? I'm really at a loss here and about to simply build the request myself...
Thanks in advance!
Upvotes: 2
Views: 127
Reputation: 817
If someone has the same problem, I ended up implementing my own ApiClient to handle my use case. The openapi-generator plugin generates an ApiClient class. Then you can do something like this to set the correct headers:
public class CustomApiClient extends ApiClient {
public CustomApiClient(OkHttpClient client) {
super(client);
}
@Override
public RequestBody buildRequestBodyMultipart(Map<String, Object> formParams) {
MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
formParams.forEach((key, value) -> {
if (value instanceof ByteArrayResource resource && "csv".equals(key)) {
requestBodyBuilder.addPart(
Headers.of("Content-Disposition", "form-data; name=\"" + key + "\"; filename=\"data.csv\""),
RequestBody.create(resource.getByteArray(), MediaType.parse("text/csv"))
);
} else {
((MultipartBody) super.buildRequestBodyMultipart(Map.of(key, value)))
.parts()
.forEach(requestBodyBuilder::addPart);
}
});
return requestBodyBuilder.build();
}
}
Its not ideal by any means, but it still uses the auto-generated methods and only alters the process for one specific formParam.
Upvotes: 0