OpenAPITools / OpenAPITools/openapi-generator

[BUG][JAVA] Generated ApiClient does not respect 'encoding' object for multipart request bodies, uses hard-coded application/octet-stream for all file form-data

Open
#16,215 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

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
post:
  operationId: uploadPdf
  requestBody:
    content:
      multipart/form-data:
        schema:
          type: object
          required:
            - pdfFile
          properties:
            pdfFile:
              type: string
              format: binary
        encoding:
          pdfFile:
            contentType: application/pdf

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's serialize 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 use Map.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:

        } else if (param.getValue() instanceof File) {
          File file = (File) param.getValue();
          String fileContentType = formParamContentTypes.getOrDefault(param.getKey(), MediaType.APPLICATION_OCTET_STREAM_TYPE)
          mp.bodyPart(new FileDataBodyPart(param.getKey(), file, fileContentType));
        }

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:

    Map<String, Object> localVarFormParams = new HashMap<String, Object>();
    Map<String, String> localVarFormParamContentTypes = new HashMap<String, String>();

Note: Changing the serialize, invokeAPI, and getAPIResponse methods would result in a breaking change if ApiClient is considered part of the public API of the generated client.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with modules/openapi-generator/src/main/resources/Java/ApiClient.mustache and api.mustache, then generate a Java client from the YAML reproduction and inspect ApiClient.java. Done means multipart file parts use each property’s encoding contentType, fall back to application/octet-stream when absent, and pass that information through invokeAPI and getAPIResponse.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.