Gereon99
Gereon99

Reputation: 817

OpenAPI generator multipart/form-data property wrong MIME type

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

Answers (1)

Gereon99
Gereon99

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

Related Questions