OpenAPITools / OpenAPITools/openapi-generator

Generated Node Express Server Wont Handle mutlipart/form-data

Open
#13,523 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Though I've used the generator for several API's this is the first time I've tried adding a route to support file upload.

I've effectively followed this documented process:
https://swagger.io/docs/specification/describing-request-body/multipart-requests/

However I have tried several variants, none of which have worked.

The path:

"/upload_video":{
      "post": {
        "description": "Upload a video or series of videos ",
        "operationId": "uploadFiles",
        "requestBody": {
          "description": "Videos to upload",
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UploadVideo"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "successful operation",
            "content": { }
          },
          "400": {
            "description": "Invalid bucket",
            "content": {}
          },
          "403": {
            "description": "Forbidden directory is not writeable or file exists but not overwritten ",
            "content": {}
          }
        },
        "deprecated": false,
        "security": [
          {
            "api_key": []
          }
        ],
        "summary": "Upload video to provided video_category.",
        "tags": [ "video_category" ]
      }
    },    

The referenced schema component:
image

I've tried with a schema using a reference (as shown above) and also inline (rather than use a reference).

I've generated both a node express service stub using:

npx ./node_modules/.bin/openapi-generator-cli generate -i InterfaceSpecification.json -g nodejs-express-server -o test_srvr_stubs

and a javascript client:
npx ./node_modules/.bin/openapi-generator-cli generate -i InterfaceSpecification.json -g javascript -o test_lib_javascript

The client library is used in a react application, and it can generate the request to the service..

However the service returns a 500 code.
image
I've dug into the service and found where it is crashing.

The error can be seen in the following print of the error:

ddd TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at Function.collectRequestParams (/home/dsargrad/dev/vm_api_svc/srvr/controllers/Controller.js:86:16)
    at Function.handleRequest (/home/dsargrad/dev/vm_api_svc/srvr/controllers/Controller.js:114:59)
    at uploadFiles (/home/dsargrad/dev/vm_api_svc/srvr/controllers/VideoCategoryController.js:25:20)
    at Layer.handle [as handle_request] (/home/dsargrad/dev/vm_api_svc/srvr/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/dsargrad/dev/vm_api_svc/srvr/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/home/dsargrad/dev/vm_api_svc/srvr/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/home/dsargrad/dev/vm_api_svc/srvr/node_modules/express/lib/router/layer.js:95:5)
    at /home/dsargrad/dev/vm_api_svc/srvr/node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/home/dsargrad/dev/vm_api_svc/srvr/node_modules/express/lib/router/index.js:346:12)

The generated code includes controllers/Controller.js

That file includes the following static method:

static collectRequestParams(request) {
    const requestParams = {};
    if (request.openapi.schema.requestBody !== undefined) {
      const { content } = request.openapi.schema.requestBody;
      if (content['application/json'] !== undefined) {
        const requestBodyName = camelCase(this.getRequestBodyName(request));
        requestParams[requestBodyName] = request.body;
      } else if (content['multipart/form-data'] !== undefined) {
        Object.keys(content['multipart/form-data'].schema.properties).forEach(
          (property) => {
            const propertyObject = content['multipart/form-data'].schema.properties[property];
            if (propertyObject.format !== undefined && propertyObject.format === 'binary') {
              requestParams[property] = this.collectFile(request, property);
            } else {
              requestParams[property] = request.body[property];
            }
          },
        );
      }
    }

    request.openapi.schema.parameters.forEach((param) => {
      if (param.in === 'path') {
        requestParams[param.name] = request.openapi.pathParams[param.name];
      } else if (param.in === 'query') {
        requestParams[param.name] = request.query[param.name];
      } else if (param.in === 'header') {
        requestParams[param.name] = request.headers[param.name];
      }
    });
    return requestParams;
  }

Notice that in the else if for multipart/form-data, it performs a forEach on
Object.keys(content['multipart/form-data'].schema.properties).forEach(

However the referenced "schema.properties" is undefined:
image

The schema includes a reference to the model:
image

This is true even if the initial model parameters was included inline (the generator generates openapi.yaml, and automatically creates a model and then references it).

I've struggled with this for a day, and would appreciate guidance.

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 the generated controllers/Controller.js collectRequestParams method and reproduce the multipart/form-data request using the referenced UploadVideo schema. Compare how the generated schema is represented in openapi.yaml with the properties access in Controller.js. Done means the generated Node Express server handles the referenced multipart schema without the TypeError and collects the upload fields.

Written by the indexing model from the issue text.

Assessment

Tech stack
express, javascript, nodejs, openapi
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.