-
Notifications
You must be signed in to change notification settings - Fork 6k
Description
Description
When processing (uploading) a file that makes use of the content type of “multipart/form-data” the current logic normalizes the parameter values to a string object, where it should be a file object.
Swagger-codegen version
Swagger Codegen 3.0.25
Swagger declaration file content or url
The issue occurs in line 428 (see attached file) when the contentType is evaluated to be of type multipart/form-data, it calls the method normalizeParams (213) where the file parameter is formatted as a string because it fails to identify as params as a file parameter.
ApiClient.zip
Partial code from the callAPI method:
if (contentType === 'application/x-www-form-urlencoded') {
request.send(querystring.stringify(this.normalizeParams(formParams)));
} else if (contentType == 'multipart/form-data') {
var _formParams = this.normalizeParams(formParams);
for (var key in _formParams) {
if (_formParams.hasOwnProperty(key)) {
if (this.isFileParam(_formParams[key])) {
// file field
request.attach(key, _formParams[key]);
} else {
request.field(key, _formParams[key]);
}
}
}
} else if (bodyParam) {
request.send(bodyParam);
}The normalizeParams method:
/**
* Normalizes parameter values:
* <ul>
* <li>remove nils</li>
* <li>keep files and arrays</li>
* <li>format to string with `paramToString` for other cases</li>
* </ul>
* @param {Object.<String, Object>} params The parameters as object properties.
* @returns {Object.<String, Object>} normalized parameters.
*/
normalizeParams(params) {
var newParams = {};
for (var key in params) {
if (params.hasOwnProperty(key) && params[key] != undefined && params[key] != null) {
var value = params[key];
if (this.isFileParam(value) || Array.isArray(value)) {
newParams[key] = value;
} else {
newParams[key] = this.paramToString(value);
}
}
}
return newParams;
}Command line used for generation
JAVA - openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)
java generate -i %YAML_PATH% -l javascript -t javascript_template -o %OUT_PATH% --additional-properties useES6=true
Steps to reproduce
Generate a javascript client SDK from and API that makes use of contentType == 'multipart/form-data'
Create an application that makes use of the SDK and attempt to upload a file to a hosting services (URL).
Related issues/PRs
Searched issues, did not find any related reported issues.
Suggest a fix/enhancement
Course of Action: 1
Add a check in the normalizeParams method to check if the value is a stream buffer (line 216)
/**
* Normalizes parameter values:
* <ul>
* <li>remove nils</li>
* <li>keep files and arrays</li>
* <li>format to string with `paramToString` for other cases</li>
* </ul>
* @param {Object.<String, Object>} params The parameters as object properties.
* @returns {Object.<String, Object>} normalized parameters.
*/
normalizeParams(params) {
var newParams = {};
for (var key in params) {
if (params.hasOwnProperty(key) && params[key] != undefined && params[key] != null || isStream.readable(value)
) {
var value = params[key];
if (this.isFileParam(value) || Array.isArray(value)) {
newParams[key] = value;
} else {
newParams[key] = this.paramToString(value);
}
}
}
return newParams;
}Course of Action 2
Add a is stream buffer check in the isFileParam method
/**
* Checks whether the given parameter value represents file-like content.
* @param param The parameter to check.
* @returns {Boolean} <code>true</code> if <code>param</code> represents a file.
*/
isFileParam(param) {
// fs.ReadStream in Node.js and Electron (but not in runtime like browserify)
if (typeof require === 'function') {
let fs;
try {
fs = require('fs');
} catch (err) {}
if (fs && fs.ReadStream && param instanceof fs.ReadStream) {
return true;
}
}
// HACK (needs import isStream from "is-stream";)
// Readstream - fs.createReadStream or fs.ReadStream
if (isStream.readable(param)) {
return true;
}
// Buffer in Node.js
if (typeof Buffer === 'function' && param instanceof Buffer) {
return true;
}
// Blob in browser
if (typeof Blob === 'function' && param instanceof Blob) {
return true;
}
// File in browser (it seems File object is also instance of Blob, but keep this for safe)
if (typeof File === 'function' && param instanceof File) {
return true;
}
return false;
}