swagger-ui
swagger-ui copied to clipboard
Inconsistent curl generated for array of objects in multipart/form-data request
Hi,
Curl command generated for a request with multipart/form-data is inconsistent/mixed. Having array of objects as form field in multipart/form-data request. Each array object is JSON object. First element is properly presented in curl command without stringify operation applied. Any array object added as result of "Add object item" button is stringified and ends as string, not an object.
Issue spotted when working on project using Python 3.8, Connexion 2.9.0, swagger-ui bundle 0.0.9 but can be reproduced on editor.swagger.io as well.
Q&A (please complete the following information)
- OS: ubuntu linux/windows
- Browser: firefox 93, Chrome Version 95.0.4638.54
- Method of installation: swagger-ui-bundle python object, editor.swagger.io
- Swagger-UI version: 3.52.0 (swagger-ui bundle 0.0.9)
- Swagger/OpenAPI version: OpenAPI 3.0.1
Content & configuration
Given below example Swagger/OpenAPI definition:
paths:
/foo:
post:
tags:
- foo
summary: bar
operationId: foo
requestBody:
description: ""
content:
multipart/form-data:
schema:
type: object
description: "zzz"
properties:
property1:
type: string
description: "property of type string, holding kind of version"
example: "1.0"
default: "1.0"
nullable: false
enum:
- "1.0"
property2:
type: array
description: array of objects
items:
type: object
description: ""
properties:
aID:
type: string
aName:
type: string
aVersion:
type: string
aLink:
type: string
example:
aID: "value aID"
aName: "value aName"
aVersion: "value aVersion"
aLink: "value aLink"
required:
- aID
- aName
- aVersion
- aLink
property3:
type: integer
format: int32
description: "property of type integer"
nullable: true
property4:
type: string
description: "yet another property of type string"
example: cow
default: cow
nullable: false
enum:
- cow
- dog
required:
- property1
- property2
encoding:
property1:
contentType: text/plain
property2:
contentType: application/json
property3:
contentType: text/plain
property4:
contentType: text/plain
responses:
200:
description: OK
content: {}
Swagger-UI configuration options: None
Describe the bug you're encountering
Produced curl command from editor.swagger.io is as follows:
curl -X 'POST' \
'https://petstore.swagger.io/v2/foo' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'property1=1.0' \
-F 'property2=[{"aID":"value aID","aName":"value aName","aVersion":"value aVersion","aLink":"value aLink"},"{\n \"aID\": \"value aID\",\n \"aName\": \"value aName\",\n \"aVersion\": \"value aVersion\",\n \"aLink\": \"value aLink\"\n}"]' \
-F 'property3=1234' \
-F 'property4=cow'
property2 is the array where first element is true JSON object, but second one is plain string and not object according to schema. In case of input validation to the API specification as is in Connexion framework the second of stringified JSON object does not pass the JSON schema validation and request is rejected.
To reproduce...
Steps to reproduce the behavior:
- Go to editor.swagger.io
- Add path with definition from example
- Navigate to endpoint in rendered swagger-ui page
- Select path foo
- Click 'try it out'
- Under property2 add array object element with button 'Add object item'
- Click Execute
- Observe generated curl command
Expected behavior
Expected curl for array of objects shall be like first element, without stringified contents of elements added with 'Add object item'
curl -X 'POST' \
'https://petstore.swagger.io/v2/foo' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'property1=1.0' \
-F 'property2=[{"aID":"value aID","aName":"value aName","aVersion":"value aVersion","aLink":"value aLink"}, {"aID":"value aID","aName":"value aName","aVersion":"value aVersion","aLink":"value aLink"}]' \
-F 'property3=1234' \
-F 'property4=cow'
Screenshots
Additional context or thoughts
Generated curl does not respect the supplied encoding in request body by not specifying the form fields with ';type=
-F 'property2=[{"aID":"value aID","aName":"value aName","aVersion":"value aVersion","aLink":"value aLink"}, {"aID":"value aID","aName":"value aName","aVersion":"value aVersion","aLink":"value aLink"}];type=application/json' \
@wojtekm462 Any secret knowledge you've obtained in the meantime that you might share with me?
I'm experiencing the same issue and haven't managed to dig out a solution
Hi, I faced the same issue, did you find any working solution?
@RedMickey I think I managed to find a workaround in Nest using @Transform
from class-transformer
. Check out this file: https://github.com/open-sauce-labs/d-reader-backend/blob/dev/src/comic-issue/dto/create-comic-issue.dto.ts
Let me know in return if you figure out how to handle multipart file uploads in nested properties! 🤣
e.g. request.body.someProperty.arrayOfObjectsWhichContainFiles
has issues with Swagger I believe
EDIT: adding the relevant code snippet in case I ever ruin the link above.
What this code does is: if the property is of type string, turn it into an array. This essentially takes care of the faulty Swagger handling and ignores all other situations.
@ArrayUnique()
@Type(() => String)
@ApiProperty({ type: [String] })
@Transform(({ value }: { value: string[] | string }) => {
if (typeof value === 'string') {
return value.split(',');
} else return value;
})
hashlist: string[];
}
Hi @josip-volarevic thanks for you reply. I managed to find the following solution:
@Post('/test/req')
@ApiConsumes('multipart/form-data')
@ApiOkResponse({schema: {example: 1}})
@ApiOperation({
requestBody: {
content: {
'multipart/form-data': {
schema: {
type: 'object',
properties: {
testParam: {
type: 'array',
items: {
type: 'string',
},
},
},
},
encoding: {
testParam: {
style: 'form',
explode: true,
},
},
},
},
},
})
@UseInterceptors(FileInterceptor('logo'))
testReq(@Req() req: Request, @Body() body: any, @UploadedFile() logo?: UploadFile) {
console.log(req.body);
return 1;
}
If I specify encoding options, then the swagger splits the array properly on sending. My workaround is based on this comment.
So, in the request body I get the following:
{ testParam: [ 'string', 'string' ] }
@RedMickey don't you now have issues with the logo
file? I don't see it anywhere on your screenshot available for upload