Parley

CIHex.pmDocs

WebSocket client for Elixir built on gen_statem and Mint WebSocket.

Full documentation on HexDocs.

Installation

Add parley to your list of dependencies in mix.exs:

def deps do
  [
    {:parley, "~> 0.3.0"}
  ]
end

Usage

Define a client module with use Parley and implement the callbacks you need:

defmodule MyClient do
  use Parley

  @impl true
  def handle_connect(state) do
    IO.puts("Connected!")
    {:ok, state}
  end

  @impl true
  def handle_frame({:text, msg}, state) do
    IO.puts("Received: #{msg}")
    {:ok, state}
  end

  @impl true
  def handle_disconnect(reason, state) do
    IO.puts("Disconnected: #{inspect(reason)}")
    {:ok, state}
  end
end

Then start the client and send frames:

{:ok, pid} = MyClient.start_link(%{}, url: "wss://example.com/ws")
Parley.send_frame(pid, {:text, "hello"})
Parley.disconnect(pid)

Options

start_link/2 accepts the following options:

The first argument is the initial state passed to init/1.

Callbacks

All callbacks are optional — default implementations are provided via use Parley.

Callback Description Return values
init(init_arg) Called when the process starts, before connecting {:ok, state}, {:stop, reason}
handle_connect(state) Called when the WebSocket handshake completes {:ok, state}, {:push, frame, state}, {:disconnect, reason, state}, {:stop, reason, state}
handle_frame(frame, state) Called when a frame is received from the server {:ok, state}, {:push, frame, state}, {:disconnect, reason, state}, {:stop, reason, state}
handle_ping(payload, state) Called when a ping is received (pong sent automatically) {:ok, state}, {:push, frame, state}, {:disconnect, reason, state}, {:stop, reason, state}
handle_info(message, state) Called when a non-WebSocket message is received {:ok, state}, {:push, frame, state}, {:disconnect, reason, state}, {:stop, reason, state}
handle_disconnect(reason, state) Called when the connection is lost or closed {:ok, state}, {:reconnect, state}, {:disconnect, state}

Frame Types

Frames are tuples matching the type {:text, String.t()} | {:binary, binary()} | {:ping, binary()} | {:pong, binary()}.

Ping frames from the server are automatically answered with pong — no user code needed.

Sends During Connection

Frames sent while the WebSocket handshake is still in progress are automatically queued and delivered once the connection is established.