Kong / insomnia

The open-source, cross-platform API client for GraphQL, REST, WebSockets, SSE and gRPC. With Cloud, Local and Git storage.
https://insomnia.rest
Apache License 2.0
34.4k stars 1.94k forks source link

[Feature Request] Multipart Form requests send percent-encoded field and file names (RFC 2231/5987) #708

Closed markgollnick closed 6 years ago

markgollnick commented 6 years ago

When using a Multipart Form request to upload one or more files with unicode code-points in the file name(s), it would be great if the Content-Disposition header parameter values could be percent-encoded per RFC 2231/5987 (see also), as some services don’t seem to accept the raw UTF-8 strings currently being sent by Insomnia.

Details

Insomnia currently sends Multipart Form requests like this when uploading a file:

POST / HTTP/1.1
Host: 127.0.0.1:5000
User-Agent: insomnia/5.12.4
Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
Accept: */*
Content-Length: 260

--X-INSOMNIA-BOUNDARY
Content-Disposition: form-data; name="file"; filename="üñîçø∂é.txt"
Content-Type: text/plain

ASCII, ISO-8859-1 (LATIN-1), and WINDOWS-1252 are dead.

Long live Üñîçø∂é and ü†ƒ-∞!

--X-INSOMNIA-BOUNDARY--

However, it would be great if users had the option to send this instead:

@@ -1,16 +1,16 @@
 POST / HTTP/1.1
 Host: 127.0.0.1:5000
 User-Agent: insomnia/5.12.4
 Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
 Accept: */*
-Content-Length: 260
+Content-Length: 296

 --X-INSOMNIA-BOUNDARY
-Content-Disposition: form-data; name="file"; filename="üñîçø∂é.txt"
+Content-Disposition: form-data; name="file"; filename*=utf-8''u%CC%88n%CC%83i%CC%82c%CC%A7%C3%B8%E2%88%82e%CC%81.txt
 Content-Type: text/plain

 ASCII, ISO-8859-1 (LATIN-1), and WINDOWS-1252 are dead.

 Long live Üñîçø∂é and ü†ƒ-∞!

 --X-INSOMNIA-BOUNDARY--

From a quick perusal of the relevant documentation, sending Content-Disposition as anything but plain ASCII seems to be a non-conformity with the specs, so at first I thought this was a bug… however, upon further investigation, it also seems that every client and user-agent under the sun (that I tested) is ignoring this and sending raw UTF-8 these days (woohoo?). I tested curl, Chrome, Firefox, Safari, Postman, etc., and to my surprise, all of them seem to send raw UTF-8. The only client or library I’ve encountered so far that actually does send percent-escaped ASCII is the Python requests library:

>>> import requests
>>> file_info = ('üñîçø∂é.txt', 'ü†ƒ-∞\n', 'text/plain; charset="UTF-8"')
>>> field_name = 'ƒîél∂-ñåmé'
>>> requests.post('http://localhost:5000/', files=[(field_name, file_info)])
POST / HTTP/1.1
Host: localhost:5000
User-Agent: python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 296
Content-Type: multipart/form-data; boundary=b18191df250b4eb6a6feedacbaa4e5b2

--b18191df250b4eb6a6feedacbaa4e5b2
Content-Disposition: form-data; name*=utf-8''%C6%92%C3%AE%C3%A9l%E2%88%82-%C3%B1%C3%A5m%C3%A9; filename*=utf-8''%C3%BC%C3%B1%C3%AE%C3%A7%C3%B8%E2%88%82%C3%A9.txt
Content-Type: text/plain; charset="UTF-8"

ü†ƒ-∞

--b18191df250b4eb6a6feedacbaa4e5b2--

So, my guess is that perhaps percent-encoding will gradually become less and less of a need in the future (woohoo!) but for now, there are still some services that depend upon it, so having the option to turn it on and off would be super handy until everything on the internet can get officially transitioned over to more modern textual codecs, and the relevant RFCs are antiquated/obsoleted by others… more quickly said than done. ;)

welcome[bot] commented 6 years ago

👋 Thanks for opening your first issue! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. If you're requesting a feature 🎁, please provide real use cases that would benefit. 👪

To help make this a smooth process, please be sure you have first read the contributing guidelines.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

o-alexandrov commented 5 years ago

Seems like it hasn't been implemented, would you like to share any info whether you plan to add support for it?

gschier commented 5 years ago

It seems like this one has fairly low demand. However, I'd be open to a community contribution as long as it's not too complicated (won't require ongoing maintenance).

I think, if it were to be added, it should be an opt-in option toggleable within the form editor.

gschier commented 5 years ago

P.S. Insomnia already performs its own multipart/form-data construction so the necessary hooks are already present.

https://github.com/getinsomnia/insomnia/blob/d9ef8b5593ce156e470a9957a26eac43d69c8af0/packages/insomnia-app/app/network/multipart.js#L65

vermgit commented 5 years ago

I don't think that there is low demand for it, it might just be that multipart POSTs aren't used that often. And as you probably know not everybody asks questions when something doesn't work, uninstalling it is done quickly ;) Especially since it's open source and free.

In fact not being able to set the content type for a part makes it - I'm sorry to say it - useless. I noticed in multipart.js that the two newlines are sent immediately after the content disposition so I have absolutely no chance to hack the body to make it work.

I'm trying to send a multipart POST where the first part is a JSON followed by two PNG-images. The server is restrictive about this and returns an error, because I failed to specify the content type for the parts. I don't think that's actually bad, it's some additional security level on the server.

Therefore, please add support for header fields per part. Or, as far as I'm concerned, at least allow to specify a content type per part.

EDIT: actually the last line is wrong. I just noticed that I also have to specify a Content-Transfer-Encoding for a use-case.

vermgit commented 5 years ago

Is there any chance that we can have support for this please?