0

I'm trying to build a function to send a file through a POST request in multipart format, using this as guide, but HTTPoison keeps giving me two errors no matter what changes I make to the form. They are all

HTTPoison.post("https://api.telegram.org/myCredentials", {:multipart, form}, headers)

and the three versions of my form and the errors are the following (whether I use headers or not):

1st and 2nd Version (same error for both):

form = [{"photo", [{"name", "myphoto.jpg"}, {:file, "files/aphoto.jpg"}]}, {"chat_id", 237799110}]
-----
form = [photo: [{"name", "myphoto.jpg"}, {:file, "files/aphoto.jpg"}], chat_id: 237799110]

Which give me this error:

** (FunctionClauseError) no function clause matching in anonymous fn/2 in :hackney_multipart.len_mp_stream/2
      (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_multipart.erl:159: anonymous fn({"photo", [{"name", "myphoto.jpg"}, {:file, "files/aphoto.jpg"}]}, 0) in :hackney_multipart.len_mp_stream/2
       (stdlib) lists.erl:1263: :lists.foldl/3
      (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_multipart.erl:159: :hackney_multipart.len_mp_stream/2
      (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_request.erl:319: :hackney_request.handle_body/4
      (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_request.erl:81: :hackney_request.perform/2
      (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney.erl:373: :hackney.send_request/2
    (httpoison) lib/httpoison/base.ex:432: HTTPoison.Base.request/9

And the third version:

form = [chat_id: 237799110, photo: [{"name", "myphoto.jpg"}, {:file, "files/aphoto.jpg"}]]

Which gives me the following error:

** (ArgumentError) argument error
              :erlang.byte_size(:chat_id)
    (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_multipart.erl:255: :hackney_multipart.mp_data_header/2
    (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_multipart.erl:180: anonymous fn/3 in :hackney_multipart.len_mp_stream/2
     (stdlib) lists.erl:1263: :lists.foldl/3
    (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_multipart.erl:159: :hackney_multipart.len_mp_stream/2
    (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_request.erl:319: :hackney_request.handle_body/4
    (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney_request.erl:81: :hackney_request.perform/2
    (hackney) c:/Users/venta/projects/elixir/wrapper/deps/hackney/src/hackney.erl:373: :hackney.send_request/2

I find invariable misfortune in the series of events that impose such obstacles over a multipart POST request, so I would like to listen to an opinion about the possible causes that lead to them.

Now, I'd be more than happy to write my own request from scratch following this format, but I'm forcing myself to use Elixir and its resources to eventually learn it after a few mishaps like this.

Community
  • 1
  • 1
Besto
  • 388
  • 1
  • 13

1 Answers1

0

Check out the documentation for HTTPoison.post/3. The 2nd argument is a body type which if you look in the docs for that type spec you will find:

body :: binary | {:form, [{atom, any}]} | {:file, binary}

Your 2nd argument doesn't match that typespec. You are sending {:multipart, form}.

This Github Issue on HTTPoison does seem to suggest you can use {:multipart, []} even though it doesn't match the documented spec, and an example test case for multipart is here.

Based on your example, maybe something like:

form = [{:file, "files/aphoto.jpg"}, {"name", "myphoto.jpg"}, {"chat_id", 237799110}]

cpjolicoeur
  • 12,766
  • 7
  • 48
  • 59
  • The problem with the form as you put it is that Telegram api requires that the file be sent within the "photo" object. Like {chat_id: destination, photo: multipart/form-data file, other parameters to modify the message sent to the api}. What do you suggest for this? – Besto Mar 20 '17 at 13:35
  • I just remembered, I have been able to send a request like this: `HTTPoison.post! url, {:form, [some: "data"]}`, which has been successfully received as form by HTTPbin – Besto Mar 20 '17 at 13:38
  • As you can see [here](https://github.com/edgurgel/httpoison/blob/master/lib/httpoison/base.ex#L160), any request that the code makes cannot have two or more arguments for `{:body, content}`, `{:form, content}`, etc., since the third argument will be processed as headers. Edit: However, it seems that multipart is not mentioned at all there. possibilities are raw binary, char list or iotlist or tuple `:form`, `:file` or `:stream` – Besto Mar 20 '17 at 13:46