Skip to content

Commit 8cfc9b0

Browse files
authored
[JS] (#7913) Adding support for multi file upload. Also adding the option for individual CodeGens to specify a collectionFormat (#7914)
* updated samples as well
1 parent 596d9a1 commit 8cfc9b0

File tree

7 files changed

+82
-13
lines changed

7 files changed

+82
-13
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5771,7 +5771,6 @@ public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body,
57715771
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
57725772
// key => property name
57735773
// value => property schema
5774-
String collectionFormat = null;
57755774
Schema s = entry.getValue();
57765775
// array of schema
57775776
if (ModelUtils.isArraySchema(s)) {
@@ -5795,6 +5794,7 @@ public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body,
57955794
}
57965795
//TODO fix collectformat for form parameters
57975796
//collectionFormat = getCollectionFormat(s);
5797+
String collectionFormat = getCollectionFormat(codegenParameter);
57985798
// default to csv:
57995799
codegenParameter.collectionFormat = StringUtils.isEmpty(collectionFormat) ? "csv" : collectionFormat;
58005800

@@ -6669,4 +6669,15 @@ protected static boolean isJsonMimeType(String mime) {
66696669
protected static boolean isJsonVendorMimeType(String mime) {
66706670
return mime != null && JSON_VENDOR_MIME_PATTERN.matcher(mime).matches();
66716671
}
6672+
6673+
/**
6674+
* Returns null by default but can be overwritten to return a valid collectionFormat
6675+
* for the {@link CodegenParameter}.
6676+
*
6677+
* @param codegenParameter parameter
6678+
* @return string for a collectionFormat.
6679+
*/
6680+
protected String getCollectionFormat(CodegenParameter codegenParameter) {
6681+
return null;
6682+
}
66726683
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavascriptClientCodegen.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,4 +1220,16 @@ public void postProcessFile(File file, String fileType) {
12201220
}
12211221
}
12221222
}
1223+
1224+
@Override
1225+
protected String getCollectionFormat(CodegenParameter codegenParameter) {
1226+
// This method will return `passthrough` when the parameter data format is binary and an array.
1227+
// `passthrough` is not part of the OAS spec. However, this will act like a flag that we should
1228+
// not do any processing on the collection type (i.e. convert to tsv, csv, etc..). This is
1229+
// critical to support multi file uploads correctly.
1230+
if (codegenParameter.isArray && Objects.equals(codegenParameter.dataFormat, "binary")) {
1231+
return "passthrough";
1232+
}
1233+
return super.getCollectionFormat(codegenParameter);
1234+
}
12231235
}

modules/openapi-generator/src/main/resources/Javascript/ApiClient.mustache

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@
316316
case 'multi':
317317
// return the array directly as SuperAgent will handle it as expected
318318
return param.map(this.paramToString, this);
319+
case 'passthrough':
320+
return param;
319321
default:
320322
throw new Error('Unknown collection format: ' + collectionFormat);
321323
}
@@ -489,11 +491,16 @@
489491
var _formParams = this.normalizeParams(formParams);
490492
for (var key in _formParams) {
491493
if (_formParams.hasOwnProperty(key)) {
492-
if (this.isFileParam(_formParams[key])) {
494+
let _formParamsValue = _formParams[key];
495+
if (this.isFileParam(_formParamsValue)) {
493496
// file field
494-
request.attach(key, _formParams[key]);
497+
request.attach(key, _formParamsValue);
498+
} else if (Array.isArray(_formParamsValue) && _formParamsValue.length
499+
&& this.isFileParam(_formParamsValue[0])) {
500+
// multiple files
501+
_formParamsValue.forEach(file => request.attach(key, file));
495502
} else {
496-
request.field(key, _formParams[key]);
503+
request.field(key, _formParamsValue);
497504
}
498505
}
499506
}

modules/openapi-generator/src/main/resources/Javascript/es6/ApiClient.mustache

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ class ApiClient {
282282
case 'multi':
283283
//return the array directly as SuperAgent will handle it as expected
284284
return param.map(this.paramToString, this);
285+
case 'passthrough':
286+
return param;
285287
default:
286288
throw new Error('Unknown collection format: ' + collectionFormat);
287289
}
@@ -451,11 +453,16 @@ class ApiClient {
451453
var _formParams = this.normalizeParams(formParams);
452454
for (var key in _formParams) {
453455
if (_formParams.hasOwnProperty(key)) {
454-
if (this.isFileParam(_formParams[key])) {
456+
let _formParamsValue = _formParams[key];
457+
if (this.isFileParam(_formParamsValue)) {
455458
// file field
456-
request.attach(key, _formParams[key]);
459+
request.attach(key, _formParamsValue);
460+
} else if (Array.isArray(_formParamsValue) && _formParamsValue.length
461+
&& this.isFileParam(_formParamsValue[0])) {
462+
// multiple files
463+
_formParamsValue.forEach(file => request.attach(key, file));
457464
} else {
458-
request.field(key, _formParams[key]);
465+
request.field(key, _formParamsValue);
459466
}
460467
}
461468
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/javascript/JavascriptClientCodegenTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717

1818
package org.openapitools.codegen.javascript;
1919

20+
import io.swagger.v3.oas.models.Components;
2021
import io.swagger.v3.oas.models.OpenAPI;
2122
import io.swagger.v3.oas.models.Operation;
23+
import io.swagger.v3.oas.models.media.ArraySchema;
24+
import io.swagger.v3.oas.models.media.MediaType;
2225
import io.swagger.v3.oas.models.media.Schema;
26+
import io.swagger.v3.oas.models.parameters.RequestBody;
2327
import org.openapitools.codegen.*;
2428
import org.openapitools.codegen.languages.JavascriptClientCodegen;
2529
import org.testng.Assert;
@@ -113,4 +117,18 @@ public void testResponseIsDefault() throws Exception {
113117

114118
}
115119

120+
@Test(description = "test multiple file upload collection is correct")
121+
public void testMultipleFileUpload() throws Exception {
122+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/form-multipart-binary-array.yaml");
123+
final JavascriptClientCodegen codegen = new JavascriptClientCodegen();
124+
codegen.setOpenAPI(openAPI);
125+
126+
final String requestPath = "/multipart-array";
127+
Operation textOperation = openAPI.getPaths().get(requestPath).getPost();
128+
CodegenOperation operation = codegen.fromOperation(requestPath, "post", textOperation, null);
129+
CodegenParameter codegenParameter = operation.allParams.get(0);
130+
131+
Assert.assertEquals(codegenParameter.collectionFormat, "passthrough");
132+
}
133+
116134
}

samples/client/petstore/javascript-es6/src/ApiClient.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ class ApiClient {
280280
case 'multi':
281281
//return the array directly as SuperAgent will handle it as expected
282282
return param.map(this.paramToString, this);
283+
case 'passthrough':
284+
return param;
283285
default:
284286
throw new Error('Unknown collection format: ' + collectionFormat);
285287
}
@@ -439,11 +441,16 @@ class ApiClient {
439441
var _formParams = this.normalizeParams(formParams);
440442
for (var key in _formParams) {
441443
if (_formParams.hasOwnProperty(key)) {
442-
if (this.isFileParam(_formParams[key])) {
444+
let _formParamsValue = _formParams[key];
445+
if (this.isFileParam(_formParamsValue)) {
443446
// file field
444-
request.attach(key, _formParams[key]);
447+
request.attach(key, _formParamsValue);
448+
} else if (Array.isArray(_formParamsValue) && _formParamsValue.length
449+
&& this.isFileParam(_formParamsValue[0])) {
450+
// multiple files
451+
_formParamsValue.forEach(file => request.attach(key, file));
445452
} else {
446-
request.field(key, _formParams[key]);
453+
request.field(key, _formParamsValue);
447454
}
448455
}
449456
}

samples/client/petstore/javascript-promise-es6/src/ApiClient.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ class ApiClient {
280280
case 'multi':
281281
//return the array directly as SuperAgent will handle it as expected
282282
return param.map(this.paramToString, this);
283+
case 'passthrough':
284+
return param;
283285
default:
284286
throw new Error('Unknown collection format: ' + collectionFormat);
285287
}
@@ -431,11 +433,16 @@ class ApiClient {
431433
var _formParams = this.normalizeParams(formParams);
432434
for (var key in _formParams) {
433435
if (_formParams.hasOwnProperty(key)) {
434-
if (this.isFileParam(_formParams[key])) {
436+
let _formParamsValue = _formParams[key];
437+
if (this.isFileParam(_formParamsValue)) {
435438
// file field
436-
request.attach(key, _formParams[key]);
439+
request.attach(key, _formParamsValue);
440+
} else if (Array.isArray(_formParamsValue) && _formParamsValue.length
441+
&& this.isFileParam(_formParamsValue[0])) {
442+
// multiple files
443+
_formParamsValue.forEach(file => request.attach(key, file));
437444
} else {
438-
request.field(key, _formParams[key]);
445+
request.field(key, _formParamsValue);
439446
}
440447
}
441448
}

0 commit comments

Comments
 (0)