lud

lud

Basic code to use mint (http client)

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 from request/5 for connection reuse. Can I do multiple requests with the same conn ? And if yes, should I use the conn from connect() or the last updated one ?

Thank you !

Most Liked

dimitarvp

dimitarvp

I highly recommend Tesla. It supports changing of the underlying HTTP client while providing a very sensible and convenient thin abstraction layer above them.

jola

jola

If you’re just looking to make some requests, look at HTTPoison (based on hackney) or Mojito (based on Mint).

Mint is a low level library which is pretty high effort if you’re not looking specifically for the features it offers. It explicitly doesn’t provide helpers to do requests, look at Mojito for that.

outlog

outlog

what @jola said - just wanted to add the tesla GitHub - elixir-tesla/tesla: The flexible HTTP client library for Elixir, with support for middleware and multiple adapters. · GitHub library which is pretty nice for creating an abstraction/module for your different requests etc..

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 130286 1222
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44139 214
New

We're in Beta

About us Mission Statement