httprb / http

HTTP (The Gem! a.k.a. http.rb) - a fast Ruby HTTP client with a chainable API, streaming support, and timeouts
MIT License
3.01k stars 321 forks source link

Specific ordering of duplicate key names for multipart data. #663

Open tom-asmblr opened 3 years ago

tom-asmblr commented 3 years ago

Hi, thanks for the great project.

I'm working with an API that requires multiple files to be uploaded such that the file metadata is followed by the file stream, repeating, with each metadata part having the name='metadata' and each file part having the name 'file' For instance, to upload two files:

Data: -----------------------1ca273...
Content-Disposition: form-data; name="metadata"

{"filename":"Report One.pdf","documentType":"Report"}
-----------------------1ca2...
Content-Disposition: form-data; name="file"; filename="stream-70139852475000"
Content-Type: application/pdf
(data for file one)
-----------------------abcdef1...
Content-Disposition: form-data; name="metadata"

{"filename":"Report Two.pdf","documentType":"Report"}
-----------------------efacd...
Content-Disposition: form-data; name="file"; filename="stream-70139852475000"
Content-Type: application/pdf
(data for file two)

Having duplicate file names seems odd, but as far as I can see in the spec it's supported, the spec also mentions maintaining the order of the parts.

Obviously using a hash to the pass in the keys doesn't work, as ruby can't have duplicate keys in a hash:

{
  metadata: '{}',
  file: '...',
  metadata: '{}',
  file: '..'
}

I've found doing the following does add all four parts, however, the order is metadata, metadata, file, file, which the API does not accept.

{
  metadata: ['{}', '{}'],
  file: ['...', '...']
}

Any idea if what I need is possible?

Thanks!

ixti commented 3 years ago

Yeah, that's doable - we will need to improve https://github.com/httprb/form_data/blob/master/lib/http/form_data/multipart.rb to accept an array pairs instead:

form: [
  ['metadata', '{}'],
  ['file', '...'],
  # ...
]