swagger-api / swagger-api/swagger-codegen
[JAVA] Bug generating request body for array of files upload
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Java code generated for request body for multi-part form data does not put the content of the files in request body, instead it places the file path and name in the request body.
Git clone and build Swagger-codegen version 3.0.5 via instructions on Github README
Swagger yaml openapi-upload-files.yaml
openapi: 3.0.0
info:
title: OpenApi file upload request body
version: "1.0.0"
contact:
name: Walt Shands
email: jshands@ucsc.edu
tags:
- name: upload_test
description: test multipart upload
paths:
/runs:
post:
summary: Upload an array of files.
description: >-
This endpoint uploads an array of files.
operationId: UploadFiles
responses:
'200':
description: ''
'400':
description: The request is malformed.
'401':
description: The request is unauthorized.
'403':
description: The requester is not authorized to perform this action.
'500':
description: An unexpected error occurred.
tags:
- UploadFilesService
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file_list:
type: array
items:
type: string
format: binary
Build client from OpenApi yaml with Swagger Codegen
java -jar <path>/swagger-codegen-cli.jar generate -l java -i <path>/openapi-upload-files.yaml
Java class used for generation of POST request
package io.arrayoffiles;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import io.swagger.client.ApiClient;
import io.swagger.client.ApiException;
import io.swagger.client.api.UploadFilesServiceApi;
public class PostArrayOfFiles {
public static void main(String[] args) {
UploadFilesServiceApi apiInstance = new UploadFilesServiceApi();
try {
ApiClient apiClient = apiInstance.getApiClient();
//apiClient.setBasePath("http://0.0.0.0:8080");
apiClient.setBasePath("http://swagger.io");
List<File> uploadFileList = new ArrayList<File>();
File testfile = new File("Users/waltershands/junk/test1.txt");
uploadFileList.add(testfile);
testfile = new File("Users/waltershands/junk/test2.txt");
uploadFileList.add(testfile);
apiInstance.uploadFiles(uploadFileList);
} catch (ApiException var4) {
System.err.println("Exception when calling uploadFileList");
var4.printStackTrace();
}
}
}
Compile test program
javac -cp <path to generated swagger client>/target/swagger-java-client-1.0.0.jar <path>/src/main/java/io/arrayoffiles/PostArrayOfFiles.java
Monitor POST requests in another terminal window
sudo tcpdump -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
Run test program
java -debug -cp <path to PostArrayOfFiles class>/target/classes:<path to generated swagger client>target/*:<path to other needed swagger jars>/target/lib/* io.arrayoffiles.PostArrayOfFiles
Produces this POST request body (seen in tcpdump window):
.... wU5POST /runs HTTP/1.1
User-Agent: Swagger-Codegen/1.0.0/java
Content-Type: multipart/form-data; boundary=e2b790d8-0149-47ac-8740-755c53c982c3
Content-Length: 223
Host: swagger.io
Connection: Keep-Alive
Accept-Encoding: gzip
--e2b790d8-0149-47ac-8740-755c53c982c3
Content-Disposition: form-data; name="file_list"
Content-Length: 67
Users/waltershands/junk/test1.txt,Users/waltershands/junk/test2.txt
--e2b790d8-0149-47ac-8740-755c53c982c3--
...
There should have been two bodies with Content-Disposition that included a 'filename="test<#>.txt" and the contents of the file
ApiClient.java creates a correct body only if the instance of the formParams Object is a File, but in the test case it is a List of Files and so the correct body is not created.
...
1109 public RequestBody buildRequestBodyMultipart(Map<String, Object> formParams) {$
1110 MultipartBuilder mpBuilder = new MultipartBuilder().type(MultipartBuilder.FORM);$
1111 for (Entry<String, Object> param : formParams.entrySet()) {$
1112 if (param.getValue() instanceof File) {$
1113 File file = (File) param.getValue();$
1114 Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + fi le.getName() + "\"");$
1115 MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file));$
1116 mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file));$
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with openapi-upload-files.yaml and the generated Java client, then inspect ApiClient.java in buildRequestBodyMultipart around lines 1109-1116. Confirm the multipart handling for a List; done means the request contains separate file parts with filenames and file contents instead of comma-joined file paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100