Background
Some time ago someone in this wonderful community suggested I used gun as an HTTP client, given that I was having severe issues with HTTPoison and later on had them with HTTPotion as well (they didn’t scale well enough).
Code
To fix it, we moved our solution to use the asynchronous HTTP client mentioned above: gun.
gun is an erlang library that communicates with a GenServer via events, calls and casts. To use gun I have therefore built a primitive GenServer client that prints to the console everything it receives:
defmodule ConnPoolWorker do
use GenServer
alias ProcessRegistry
alias :gun, as: Gun
@url_domain 'google.com'
@https_port 443
def start_link({worker_id}) do
IO.puts("Starting worker #{worker_id}")
GenServer.start_link(
__MODULE__,
nil,
name: via_tuple(worker_id)
)
end
## Public API
#makes a GET request via gun
def fire(worker_id, url) do
GenServer.cast(via_tuple(worker_id), {:fire, url})
end
## Implementation
defp via_tuple(worker_id) do
ProcessRegistry.via_tuple({__MODULE__, worker_id})
end
@impl GenServer
def init(_args) do
{:ok, conn_pid} = Gun.open(@url_domain, @https_port)
{:ok, _protocol} = Gun.await_up(conn_pid)
{:ok, conn_pid}
end
@impl GenServer
def handle_cast({:fire, url}, conn_pid) do
Gun.get(conn_pid, url)
{:noreply, conn_pid}
end
# handle_info everything else
@impl GenServer
def handle_info(msg, state) do
IO.puts("MSG: #{inspect msg}")
{:noreply, state}
end
end
This client is registered in the Registry using via_tuples, but I don’t think that is majorly important for now.
Problem
This code works. It opens a connections, waits for the connection to be up, and if you invoke fire to make a request (get it? because the library is called gun?
) you get a :gun_response event that handle_info picks up.
However, that’s precisely the issue. It’s the only event the process ever picks up. This process gets no other events like :gun_data or :gun_trailers, even though the documentation says it should.
The only thing I get every now and then is a :gun_down (connection down) followed by a :gun_up (connection up) which is normal:
MSG: {:gun_response, #PID<0.214.0>, #Reference<0.1474087065.2991849473.15656>, :fin, 302, [{"server", "nginx"}, {"date", "Wed, 20 Feb 2019 11:55:14 GMT"}, {"content-length", "0"}, {"connection", "keep-alive"}, {"location", "http://www.sapo.pt/noticias/"}, {"strict-transport-security", "max-age=31536000"}, {"x-content-type-options", "nosniff"}, {"content-security-policy", "upgrade-insecure-requests; block-all-mixed-content"}, {"x-xss-protection", "1; mode=block"}, {"referrer-policy", "origin-when-cross-origin"}]}
MSG: {:gun_down, #PID<0.221.0>, :http, :closed, [], []}
MSG: {:gun_down, #PID<0.224.0>, :http, :closed, [], []}
Question
- Am I doing something wrong with my
GenServerclient? - Is this working as intended or am I missing something?
- How can I get the rest of the data from the request?






















