hackney provides a WebSocket client with process-per-connection architecture.
Quick Start
{ok, Conn} = hackney:ws_connect(<<"wss://echo.websocket.org">>),
ok = hackney:ws_send(Conn, {text, <<"Hello!">>}),
{ok, {text, <<"Hello!">>}} = hackney:ws_recv(Conn),
hackney:ws_close(Conn).
Connecting
Simple Connection
{ok, Conn} = hackney:ws_connect(<<"wss://example.com/socket">>).
Connection with Options
{ok, Conn} = hackney:ws_connect(<<"wss://example.com/socket">>, [
{connect_timeout, 5000},
{recv_timeout, 30000},
{headers, [{<<"authorization">>, <<"Bearer token">>}]},
{protocols, [<<"graphql-ws">>]}
]).
Available Options
| Option | Default | Description |
|---|
connect_timeout | 8000 | TCP connection timeout (ms) |
recv_timeout | infinity | Receive timeout (ms) |
headers | [] | Extra headers for upgrade |
protocols | [] | Sec-WebSocket-Protocol values |
active | false | Active mode: false, true, once |
ssl_options | [] | SSL options for wss:// |
Sending Messages
Text Messages
ok = hackney:ws_send(Conn, {text, <<"Hello">>}).
Binary Messages
ok = hackney:ws_send(Conn, {binary, <<1, 2, 3>>}).
Ping/Pong
ok = hackney:ws_send(Conn, ping).
ok = hackney:ws_send(Conn, {ping, <<"heartbeat">>}).
Receiving Messages
Passive Mode (Default)
{ok, Frame} = hackney:ws_recv(Conn).
{ok, Frame} = hackney:ws_recv(Conn, 5000). %% With timeout
Frame Types
case hackney:ws_recv(Conn) of
{ok, {text, Text}} -> handle_text(Text);
{ok, {binary, Data}} -> handle_binary(Data);
{ok, ping} -> ok; %% Auto-responded
{ok, pong} -> ok;
{error, {closed, Code, Reason}} -> handle_close(Code)
end.
Active Mode
Enable Active Mode
{ok, Conn} = hackney:ws_connect(URL, [{active, true}]).
%% Or later:
hackney:ws_setopts(Conn, [{active, true}]).
Receive Messages
receive
{hackney_ws, Conn, {text, Text}} -> handle(Text);
{hackney_ws, Conn, closed} -> done;
{hackney_ws_error, Conn, Reason} -> error
end.
Active Once
{ok, Conn} = hackney:ws_connect(URL, [{active, once}]),
receive {hackney_ws, Conn, Frame} -> ok end,
hackney:ws_setopts(Conn, [{active, once}]). %% Get next
Closing Connections
hackney:ws_close(Conn).
hackney:ws_close(Conn, {1000, <<"Goodbye">>}).
Close Codes
| Code | Meaning |
|---|
| 1000 | Normal closure |
| 1001 | Going away |
| 1002 | Protocol error |
Example: Chat Client
-module(chat).
-export([start/1, send/2]).
start(URL) ->
{ok, Conn} = hackney:ws_connect(URL, [{active, true}]),
spawn(fun() -> loop(Conn) end),
Conn.
send(Conn, Msg) ->
hackney:ws_send(Conn, {text, Msg}).
loop(Conn) ->
receive
{hackney_ws, Conn, {text, Text}} ->
io:format("~s~n", [Text]),
loop(Conn);
{hackney_ws, Conn, closed} ->
ok
end.
Error Handling
case hackney:ws_connect(URL) of
{ok, Conn} -> use(Conn);
{error, {http_error, 401}} -> unauthorized;
{error, timeout} -> timeout;
{error, Reason} -> {error, Reason}
end.
Next Steps