OpenAPITools / OpenAPITools/openapi-generator

[BUG] Multipart File upload does not work for generated Ktor clients due to missing content disposition headers

Open
#19,644 1 comment 1 reaction 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

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Multipart file upload using generated client does not work due to missing filename in content disposition headers. I generated a client against an upload API in Kotlin Spring. When using the generated client to upload a file Spring returns status 400 indicating the file has not been uploaded. After a bit of digging I found that Spring is expecting the filename in content disposition but its missing from the generated client.

Actual Output: Returns status 400 due to file missing
Expected Output: The file should be uploaded and return a status 200

The issue seemed to resolve when I manually added the headers.

openapi-generator version

7.8.0 ( I did observe this issue in older versions as well.)

OpenAPI declaration file content or url

https://gist.github.com/JishnuRamesh/4aa53186b4725f6daff11aee641e3ee3

Generation Details

The API application is created using spring boot.
Code was generated using the below configuration

    tasks.register<org.openapitools.generator.gradle.plugin.tasks.GenerateTask>("generateClient") {
    generatorName.set("kotlin")
    inputSpec.set("$projectDir/swagger.json") 
    outputDir.set("$projectDir/src/main/kotlin")
    apiPackage.set("org.example.api")
    modelPackage.set("org.example.api.model")
    configOptions.set(mapOf("dateLibrary" to "java8"))
    additionalProperties.set(mapOf("java8" to "true"))
    skipOverwrite.set(true)
    verbose.set(true)
    validateSpec.set(false)
    library.set("jvm-ktor")
}
Steps to reproduce
  1. Create a multipart file upload API in Spring
  2. Use the swagger.json to generate a ktor client for the upload API
  3. try uploading a file using the generated client

Spring will respond with 400 with the error required field file is missing. I narrowed down the issue to be that the generated client is missing HTTP Headers ContentDisposition with filename. If I manually add this header then the API call works as expected as shown below

                        formData {
                        file?.apply { append("file", file, Headers.build {
                            append(HttpHeaders.ContentDisposition, "filename=\"file\"") })} // this header missing
                        }
Related issues/PRs

A similar issue was raised here

Files

GeneratedUploadApi.kt.txt
GeneratedUploadApiFixed.kt.txt
Upload.kt.txt

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 by comparing the attached GeneratedUploadApi.kt.txt and GeneratedUploadApiFixed.kt.txt, then inspect the Kotlin jvm-ktor generator templates used by the Gradle configuration. Reproduce the multipart upload with the linked OpenAPI declaration and verify that the generated request includes the filename in Content-Disposition and returns a successful upload response.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
43/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.