OpenAPITools / OpenAPITools/openapi-generator

[BUG] golang client file upload

Open
#21,499 0 comments 0 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

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

The generated Go client has a critical bug in the setBody function that prevents any request body type from being correctly processed. All type assertions fail due to an extra pointer wrapping layer introduced by the Body() method. This affects all HTTP methods that send request bodies (PUT, POST, PATCH).

When calling .Body(data) with any data type ([]byte, string, *os.File, io.Reader, etc.), the data gets wrapped in *interface{} but the setBody function expects unwrapped types, causing all type assertions to fail.

openapi-generator version

7.12.0

OpenAPI declaration file content or url
{
  "openapi": "3.0.1",
  "info": {
    "title": "nexus",
    "description": "Artifact repository.",
    "version": "v1"
  },
  "tags": [
    {
      "name": "Artifact"
    }
  ],
  "paths": {
    "/repository/{path}": {
      "get": {
        "tags": [
          "Artifact"
        ],
        "summary": "get artifact",
        "operationId": "getArtifact",
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Bad Request"
          },
          "404": {
            "description": "Not found"
          },
          "500": {
            "description": "Internal Server Error"
          }
        }
      },
      "put": {
        "tags": [
          "Artifact"
        ],
        "summary": "put artifact",
        "operationId": "putArtifact",
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "*/*": {
              "schema": {
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Bad Request"
          },
          "404": {
            "description": "Not found"
          },
          "500": {
            "description": "Internal Server Error"
          }
        }
      }
    }
  }
}

Generation Details

Generated Go client using openapi-generator for the above spec.

Steps to reproduce
  1. Generate Go client from OpenAPI spec with binary upload endpoint
  2. Try to upload data using any body type:
// All of these do not upload the expected content
client.PutArtifact(ctx, "path").Body([]byte("data")).Execute()
client.PutArtifact(ctx, "path").Body("data").Execute() 
client.PutArtifact(ctx, "path").Body(file).Execute() // *os.File
client.PutArtifact(ctx, "path").Body(reader).Execute() // io.Reader
  1. Observe that type assertions in setBody() fail silently and request body is not set correctly
Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/issues/11542

Suggest a fix

The issue is in two locations:

Root cause in Body() method (api_*.go):

func (r ApiPutArtifactRequest) Body(body interface{}) ApiPutArtifactRequest {
    r.body = &body  // ← Creates *interface{} wrapper
    return r
}

Failed type assertions in setBody() (client.go):

// These all fail because body is *interface{}, not the expected types
if reader, ok := body.(io.Reader); ok {
if fp, ok := body.(*os.File); ok {
if b, ok := body.([]byte); ok {

Suggested fix - Add to beginning of setBody() function:

func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
    // Unwrap pointer wrapper added by Body() method
    if bodyPtr, ok := body.(*interface{}); ok {
        body = *bodyPtr
    }
    
    if bodyBuf == nil {
        bodyBuf = &bytes.Buffer{}
    }
    // ... rest of existing code unchanged
}

Alternative fix - In Execute methods:

// Change from:
localVarPostBody = r.body

// To:
if r.body != nil {
    localVarPostBody = *r.body
} else {
    localVarPostBody = r.body
}
What's the actual output vs expected output?

Expected: Request body should be properly set based on the input type
Actual: All type assertions fail, request body defaults to JSON encoding or remains empty, causing upload failures and silent failures

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

Inspect the generated api_*.go Body method and client.go setBody function described in the report, then generate a Go client from the provided binary-upload OpenAPI spec. Verify uploads with []byte, string, *os.File, and io.Reader inputs; done means each request body is populated correctly for PUT, POST, and PATCH without silent type-assertion failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.