Okay, I spent some time looking into this and there are a few things going on:
- Are mixing
application/x-www-form-urlencoded
andmultipart/form-data
content types - In the latter case, not including the boundary in the header
When you pass something to the form
property, it internally overrides your Content-Type
header to application/x-www-form-urlencoded
, yet the body of the request is multipart/form-data
. You can reproduce this in Postman too by unchecking the default Content-Type
header and adding a custom one with application/x-www-form-urlencoded
.
Ultimately the fix is to settle on one or the other:
# application/x-www-form-urlencoded
response = HTTP::Client.post(
url: "https://freeimage.host/api/1/upload",
form: {
"key" => "my_key",
"source" => "https://avatars.githubusercontent.com/u/549126?s=96&v=4",
}
)
However, because you said you’re going to be uploading files, will likely want to use multipart/form-data
. Which you’d want to handle by just passing it as the body. E.g. body: io.rewind
. But there is still one thing missing. The content-type
headers needs the boundary for multipart requests. Which you can get from the HTTP::FormData::Builder
instance:
io = IO::Memory.new
form_data = HTTP::FormData::Builder.new(io)
form_data.field("key", "my_key")
form_data.field("source", "https://avatars.githubusercontent.com/u/549126?s=96&v=4")
form_data.finish
response = HTTP::Client.post(
url: "https://freeimage.host/api/1/upload",
headers: HTTP::Headers{"content-type" => form_data.content_type},
body: io.rewind
)