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
GenServer
client? - Is this working as intended or am I missing something?
- How can I get the rest of the data from the request?