swagger-api / swagger-api/swagger-codegen

[typescript-angular] multipart/form-data submissions include filename="blob" which confuses backends

Open
#9,940 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

I am having an issue with the typescript-angular generated code. I have an openapi spec which uses a multipart/form-data request that includes both a file and a json document field.

The multipart body in the request, when submitted by chrome, tends to look like this:

POST /api/1.0/item/add HTTP/1.1
...
content-type: multipart/form-data; boundary=----WebKitFormBoundaryOsISlkzGT7TAuz5W

------WebKitFormBoundaryOsISlkzGT7TAuz5W
Content-Disposition: form-data; name="media"; filename="foo.wav"
Content-Type: audio/wav

RIFF...
...
------WebKitFormBoundaryWC8tMAERR4StMjHj
Content-Disposition: form-data; name="info"; filename="blob"
Content-Type: application/json

{"type":"audio","tags":["green","red"], ... }
------WebKitFormBoundaryWC8tMAERR4StMjHj--

The issue is that the json document (info), which was not from an <input type='file'...>, contains a filename="blob" value. When a backend receives this, it cannot tell the difference between an entity is should write to a temp file before calling the handler (a typical behavior) or just a string field which has a given a content type.

I'm using python's aiohttp to receive the request, and since filename has a value, it's returning this as a aiohttp.web.FileField(). I tracked that down to here: https://github.com/aio-libs/aiohttp/blob/master/aiohttp/web_request.py#L621

I didn't test it, but I believe a Flask backed would treat it the same way: https://github.com/pallets/werkzeug/blob/master/src/werkzeug/formparser.py#L467

This happens because the generated typescript-angular service eventually does this...

   formParams = new FormData();
...
  formParams = formParams.append('info', useForm ? new Blob([JSON.stringify(info)], { type: 'application/json' }) : info) || formParams;

... when building the request. This seems basically correct. The docs for FormData.append() says that if a Blob() is passed, this the default filename will be "blob" (as I'm observing) but can vary from browser to browser. See https://developer.mozilla.org/en-US/docs/Web/API/FormData/append

However, if I pass "" as the 3rd optional parameter for a filename, then the request body still contains filename="", but the backends then treat them as non-files, and everything works from there on out.

I didn't find all this out until I started using the browser. My unit tests, using curl -F "{json};type=application/json" didn't feel the need to include a filename component in the content-disposition field.

Swagger-codegen version

Version 2.4.10 (probably not a regresssion)

Suggest a fix/enhancement

I was going to suggest adding "" when calling append() for blobs. I can make a PR, but do we think it would be accepted? Is existing code expecting a value of blob or whatever unpredictable value it may have depending on the browser?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the typescript-angular service generation path that builds FormData and the FormData.append('info', ...) entry point shown in the report. Review the existing unit coverage, noting that the reported curl-based test does not include a filename component. Done means JSON Blob parts are submitted without a misleading default filename and regression coverage verifies the multipart behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, typescript
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.