openapi-typescript-codegen icon indicating copy to clipboard operation
openapi-typescript-codegen copied to clipboard

formData of openapi V3 not parsed

Open nichujie opened this issue 3 years ago • 6 comments

I used [email protected] to parse the openapi.json generated by our backend(which uses FastAPI). I find that one of the api is mis-parsed as a request that sends json rather than form-data. I've tested this api and it really can process form-data request. Here's the schema in openapi.json.

{
"openapi": "3.0.2",
  "info": {
    "title": "JOJ Horse",
    "description": "Git version: e43226b",
    "version": "0.0.1"
  },
  "paths": {
    "/api/v1/problems/{problem_set}/{problem}": {
      "post": {
        "tags": [
          "problem"
        ],
        "summary": "Submit Solution To Problem",
        "operationId": "submit_solution_to_problem_api_v1_problems__problem_set___problem__post",
        "parameters": [
          {
            "required": true,
            "schema": {
              "title": "Problem Set",
              "type": "string"
            },
            "name": "problem_set",
            "in": "path"
          },
          {
            "required": true,
            "schema": {
              "title": "Problem",
              "type": "string"
            },
            "name": "problem",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CodeFile"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordResp"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    }
  }
}

And the code generated is like:

public static async submitSolutionToProblemApiV1ProblemsProblemSetProblemPost(
        problemSet: string,
        problem: string,
        requestBody: any,
    ): Promise<RecordResp> {
        const result = await __request({
            method: 'POST',
            path: `/api/v1/problems/${problemSet}/${problem}`,
            body: requestBody,  // Can this be "formData: requestBody" ?
            errors: {
                422: `Validation Error`,
            },
        });
        return result.body;
    }

I can't figure out how to make the requestBody to be formData rather than body. The schema seems to state the request type correctly.

Also, I can't find multipart/form-data examples in the sample you provided. Even the uploadFile method is parsed to use query strings.

nichujie avatar May 12 '21 08:05 nichujie

Happy to see #257 describes exactly the same problem, and see that already in the roadmap. Looking forward to see it fixed!

nichujie avatar May 12 '21 12:05 nichujie

@nichujie This should be fixed now. 0.11.4 should have partial multi-part form data support (to start with). Could you validate if this works correctly now?

ferdikoomen avatar Oct 28 '21 18:10 ferdikoomen

@ferdikoomen hi there! I've just checked submit multi-part form data it doesn't support arrays at all, so

"requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "files": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    }
                  }
                }
              },

run code like this const res = await fileServiceApi.fileUpload({ formData: { files: [file] } }) won't be processed due to Array type

if you post it as const res = await fileServiceApi.fileUpload({ formData: { files: file } }) it works properly but rises TypeScript issue with matching types

This swagger will work correct:

"requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "files": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              },

It's nice to have:

  • Support for Arrays in formData
  • Add some docs how to use request with multi-part data (I was reading sources at least to understand that I don't need create new formData object by myself, was stuck with formData field rewrites by library code)

Anyway for plain data we can close #695 #257

cale148 avatar Nov 17 '21 09:11 cale148

@cale148 let me quickly validate what we can do with arrays these should indeed just get converted to multipart data. Will push a fix first before closing this ticket (#695)

ferdikoomen avatar Nov 17 '21 10:11 ferdikoomen

@cale148 dis you try it with the following spec:

"requestBody": {
    "content": {
        "multipart/form-data": {
            "schema": {
                "type": "array",
                "items": {
                    "type": "string",
                    "format": "binary"
                }
            }
        }
    }
},

I am testing some things now but the first one with the 'files' property does not work indeed. FormData needs an array of files in order to properly create the multipart data

ferdikoomen avatar Nov 17 '21 11:11 ferdikoomen

@ferdikoomen unfortunately I'm not doing backend and don't have environment to roll it out on my machine. I've just tested on real API which I work with :)

cale148 avatar Nov 17 '21 11:11 cale148