Hello,
I am trying to use mint to make some http requests with Elixir, and reading the docs I wrote the following code.
It works fine (for basic GET requests and everything is hardcoded, it’s normal, just a test) but it seems a bit to much to use a library.
Questions at the end of the post.
defmodule HTTP do
@empty_state %{data: [], done: false}
def run do
with {:ok, conn} <- Mint.HTTP.connect(:http, "httpbin.org", 80),
{:ok, conn, _ref} <- Mint.HTTP.request(conn, "GET", "/", [], nil) do
handle_response(conn, @empty_state)
end
end
defp handle_response(conn, state) do
receive do
message ->
case Mint.HTTP.stream(conn, message) do
{:ok, conn, responses} ->
case Enum.reduce(responses, state, &handle_res/2) do
# Loop ends here
%{done: true} = state -> {:ok, state}
%{done: false} = state -> handle_response(conn, state)
end
{:error, _, reason, _} ->
{:error, reason}
:unknown ->
exit({:unexpected, message})
end
end
end
defp handle_res({:status, _, status}, state),
do: Map.put(state, :status, status)
defp handle_res({:headers, _, headers}, state),
do: Map.put(state, :headers, headers)
defp handle_res({:data, _, data}, state),
do: Map.update!(state, :data, fn acc -> [data | acc] end)
defp handle_res({:done, _}, state) do
Map.update!(state, :data, fn acc ->
acc
|> :lists.reverse()
|> Enum.join("")
end)
|> Map.put(:done, true)
end
end
Task.async(fn -> HTTP.run() end)
|> Task.await()
|> case do
{:ok, state} ->
state
|> Map.get(:data)
|> IO.puts()
other ->
IO.inspect(other, pretty: true)
end
A quick note : I intend to use this from a GenServer, and I have no concerns about performance for this project, so to avoid handling messages, I will spawn a Task
to handle the request, so I do not care about the request reference or :unknown
messages. Also I know there are other responses possibles.
But again I do not expect other messages.
Questions
- Is my code
:ok
? I’ll take any remarks. - Am I expected to do that to use this library ?
- Do you think
mint
should provide a helper like this for basic single requests ? - If I got it right,
connect/3
is separated fromrequest/5
for connection reuse. Can I do multiple requests with the sameconn
? And if yes, should I use the conn fromconnect()
or the last updated one ?
Thank you !