swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.88k stars 6.03k forks source link

[Javascript] File is not uploaded. (The documentation of generated Javascript code is wrong.) #9253

Open NullP0interEx opened 5 years ago

NullP0interEx commented 5 years ago
Description

The request is not executed correctly. The file will not be uploaded. The parameter "file" is just the file name, instead of the binary data.

Swagger-codegen version

openapi-generator-cli-3.3.4.jar

Swagger declaration file content or url

Swagger .yaml:

  /orders/upload:
    post:
      operationId: "orderUploadPart"
      summary: "upload a textual or audio part of an order"
      tags:
        - "orders"
      description: "This funktion uploads a textual or audio part of an order to the sense.ai.tion cloud system. 
      The result is the resource identifier, that must be used in the order request."
      consumes:
        - multipart/form-data
      parameters:
        - in: "formData"
          name: "file"
          type: "file"
          required: true
          description: "the file to upload"
        - in: "formData"
          name: "media"
          type: "string"
          enum:
            - "text"
            - "wav"
            - "mp3"
          required: true
          description: "the media type of the the upload, can be ***text***, ***wav*** or ***mp3***"

Code:

var apiInstance = new SenseaitionApi.OrdersApi();
var file = "/path/to/file"; // File | the file to upload
var media = "media_example"; // String | the media type of the the upload, can be ***text***, ***wav*** or ***mp3***
var callback = function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('API called successfully. Returned data: ' + data);
  }
};
apiInstance.orderUploadPart(file, media, callback);

image

Command line used for generation

java -jar ${GOPATH}/bin/openapi-generator-cli.jar generate -i service_js_api.yaml -g javascript -o clients/javascript/senseaition-api-js -Dio.swagger.parser.util.RemoteUrl.trustAll=true

Steps to reproduce

just run sample code

NullP0interEx commented 5 years ago

I found the mistake. The documentation of generated Javascript code is wrong. For uploading a file (Javascript object) must be passed, not the Path.

This line is wrong:

var file = "/path/to/file"; // File | the file to upload 
cladera commented 5 years ago

It is not only wrong the documentation, it is also wrong how the file is being attached.

At ApiClient.prototype.callApi, when the file param is a Buffer (node.js) superagent's attach method expects a third param which should be either the file name or an options object. Otherwise the file is not properly included in the request and therefore it fails.

cladera commented 5 years ago

I just found a workaround. As I said, the attach method expects a third param, however, if the file object provided contains a path property and the third argument is not provided it will use it as the filename.

Superagent attach implementation:

Request.prototype.attach = function(field, file, filename){
  if (!this._formData) this._formData = new FormData();
  if ('string' == typeof file) {
    if (!filename) filename = file;
    debug('creating `fs.ReadStream` instance for file: %s', file);
    file = fs.createReadStream(file);
  } else if(!filename && file.path) {
    filename = file.path;
  }
  this._formData.append(field, file, { filename: filename });
  return this;
};

Workaround with swagger generated sdk:

const api = require('api');
const files = new api.FilesApi();

const file = Buffer.from('Hello world', 'utf-8');

// Set path property to make superagent use it as filename
file.path = 'file.txt';

files.upload(file);

Despite this way to make it work, I believe ApiClient should accept path-like strings as valid files params.