View Source Fresh behaviour (Fresh v0.3.0)
Callback behaviours and functions for WebSocket client.
Summary
Types
Represents the response for all connection handle callback.
Represents control frames in a WebSocket connection.
Represents data frames in a WebSocket connection.
Represents various error scenarios that can occur during WebSocket communication.
Represents the response of a generic callback and enables you to manage state.
Represents optional configurations for WebSocket configuration.
Represents the state of the given module, which can be anything.
Callbacks
Callback is invoked when a WebSocket connection is successfully established.
Callback is invoked when a control frame is received from the server.
Callback is invoked when the WebSocket connection is being disconnected.
Callback is invoked when an error occurs, allows you to define custom error handling logic to handle various scenarios gracefully.
Callback is invoked when a data frame is received from the server.
Callback is invoked when an incomprehensible message is received.
Callback is invoked when the process is about to terminate.
Functions
This macro simplifies the implementation of WebSocket client. It automatically configures child_spec/1
, start/1
and start_link/1
for the module, and provides empty handlers for all required callbacks, which can be overridden.
Sends a WebSocket close frame to the server.
Sends a WebSocket frame to the server.
Starts a WebSocket connection without linking process. Refer to start_link/4
for more information.
Starts a WebSocket connection.
Types
@type connection_handle_response() :: {:ignore, state()} | {:reconnect, state()} | {:close, term()} | :reconnect | :close
Represents the response for all connection handle callback.
{:ignore, state}
: Indicates an intent to ignore and continue.Example:
{:ignore, state}
{:reconnect, state}
: Indicates an intent to reconnect, with given state.Example:
{:reconnect, 0}
{:close, reason}
: Indicates an intent to close connection, with custom reason. Can be used to force Supervisor to restart process.Example:
{:close, {:error, :unknown}}
:reconnect
: Indicates an intent to reconnect, with initial state.:close
: Indicates an intent to close connection normally.
Represents control frames in a WebSocket connection.
Represents data frames in a WebSocket connection.
@type error() :: {:connecting_failed, Mint.Types.error()} | {:upgrading_failed, Mint.WebSocket.error()} | {:streaming_failed, Mint.Types.error()} | {:establishing_failed, Mint.WebSocket.error()} | {:processing_failed, term()} | {:decoding_failed, any()} | {:encoding_failed, any()} | {:casting_failed, Mint.WebSocket.error()}
Represents various error scenarios that can occur during WebSocket communication.
@type generic_handle_response() :: {:ok, state()} | {:reply, [Mint.WebSocket.frame()], state()} | {:close, non_neg_integer(), binary(), state()}
Represents the response of a generic callback and enables you to manage state.
{:ok, state}
: Indicates a successful operation.Examples:
{:ok, state + 1}
,{:ok, state}
{:reply, frames, state}
: Denotes a successful operation with a list of WebSocket frames sent as a reply to the server.Example:
{:reply, [{:text, "Bousou"}, {:text, "暴走"}], state}
{:close, code, reason, state}
: Signifies the closure of the connection with a non-negative integercode
and a binaryreason
.Example:
{:close, 1000, "Normal Closure", state}
- Normal closure with a reason and no state change.
@type option() :: {:name, :gen_statem.server_name()} | {:headers, Mint.Types.headers()} | {:transport_opts, keyword()} | {:mint_upgrade_opts, keyword()} | {:ping_interval, non_neg_integer()} | {:error_logging, boolean()} | {:info_logging, boolean()}
Represents optional configurations for WebSocket configuration.
:name
: Registers a name for the WebSocket connection, allowing you to refer to it later using a name.Example:
{:local, Example.WebSocket}
:headers
: A list of headers to include in the WebSocket connection request. These headers will be sent during the connection upgrade.Example:
{:headers, [{"Authorization", "Bearer token"}]}
:transport_opts
: Additional options to pass to the transport layer used for the WebSocket connection. Consult the Mint.HTTP documentation for more informations.Example:
{:transport_opts, [cacertfile: "/my/file"]}
:mint_upgrade_opts
: Extra options to provide to Mint.WebSocket during the WebSocket upgrade process. Consult the Mint.WebSocket documentation for additional information.Example:
{:mint_upgrade_opts, [extensions: [Mint.WebSocket.PerMessageDeflate]]}
:ping_interval
: This option is used to keep connection alive by sending empty ping frames based on given time as milliseconds. By default it is set to30000
. To disable it, set it to0
.Example:
{:ping_interval, 60_000}
:error_logging
: Allows you to toggle logging forerror/0
error(s). Enabled by default.Example:
{:error_logging, false}
:info_logging
: Allows you to toggle logging information message(s). Enabled by default.Example:
{:info_logging, false}
@type state() :: any()
Represents the state of the given module, which can be anything.
Callbacks
@callback handle_connect(status, headers, state()) :: generic_handle_response() when status: Mint.Types.status(), headers: Mint.Types.headers()
Callback is invoked when a WebSocket connection is successfully established.
status
: The status received during the connection upgrade.headers
: The headers received during the connection upgrade.Example:
[{"upgrade", "websocket"}, {"connection", "upgrade"}]
state
: The current state of the module.
Example
def handle_connect(_status, _headers, state) do
payload = "{ \"op\": 1, \"data\": {} }"
{:reply, [{:text, payload}], state}
end
@callback handle_control(frame :: control_frame(), state()) :: generic_handle_response()
Callback is invoked when a control frame is received from the server.
frame
: The received WebSocket frame.state
: The current state of the module.
Example
def handle_control({:ping, message}, state) do
IO.puts("Received ping with content: #{message}!")
{:ok, state}
end
def handle_control({:pong, message}, state) do
IO.puts("Received pong with content: #{message}!")
{:ok, state}
end
@callback handle_disconnect(code, reason, state()) :: connection_handle_response() when code: non_neg_integer() | nil, reason: binary() | nil
Callback is invoked when the WebSocket connection is being disconnected.
code
: The disconnection code (if available).Example:
1002
reason
: The reason for the disconnection (if available).Example:
"timeout"
state
: The current state of the module.
Example
def handle_disconnect(1002, _reason, _state), do: :reconnect
def handle_disconnect(_code, _reason, _state), do: :close
@callback handle_error(error(), state()) :: connection_handle_response()
Callback is invoked when an error occurs, allows you to define custom error handling logic to handle various scenarios gracefully.
error
: The encountered error.state
: The current state of the module.
Example
def handle_error({error, _reason}, state)
when error in [:encoding_failed, :casting_failed],
do: {:ignore, state}
def handle_error(_error, _state), do: :reconnect
@callback handle_in(frame :: data_frame(), state()) :: generic_handle_response()
Callback is invoked when a data frame is received from the server.
frame
: The received WebSocket frame.state
: The current state of the module.
Example
def handle_in({:text, message}, state) do
%{"data" => updated_data} = Jason.decode!(message)
{:ok, updated_data}
end
def handle_in({:binary, _message}, state) do
{:reply, [{:text, "i don't accept binary!"}], state}
end
@callback handle_info(data :: any(), state()) :: generic_handle_response()
Callback is invoked when an incomprehensible message is received.
data
: The received message.state
: The current state of the module.
Example
def handle_info({:reply, message}, state) do
{:reply, [{:text, message}], state}
end
Can be used like:
send(:ws_conn, {:reply, "hello!"})
Callback is invoked when the process is about to terminate.
reason
: The reason for the termination.Example:
:normal
,:shutdown
,{:error, :unknown_data}
state
: The current state of the module.
Return value is always ignored.
Example
def handle_terminate(reason, _state) do
IO.puts("Process is terminating with reason: #{inspect(reason)}")
end
Functions
This macro simplifies the implementation of WebSocket client. It automatically configures child_spec/1
, start/1
and start_link/1
for the module, and provides empty handlers for all required callbacks, which can be overridden.
Starting the WebSocket client using start_link/1
with the desired options:
iex> Example.WebSocket.start_link(uri: "wss://example.com/socket", state: %{}, opts: [
iex> name: {:local, :ws_conn}
iex> ])
{:ok, #PID<0.233.0>}
Starting the WebSocket client using Supervisor (recommended):
children = [
{Example.WebSocket,
uri: "wss://example.com/socket",
state: %{},
opts: [
name: {:local, :ws_conn}
]}
# Add other child specifications...
]
Supervisor.start_link(children, strategy: :one_for_one)
@spec close(:gen_statem.server_ref(), non_neg_integer(), binary()) :: :ok
Sends a WebSocket close frame to the server.
pid
: The WebSocket connection process.code
: WebSocket close code.Example:
1000
reason
: WebSocket close reason.Example:
"dunno"
Example
iex> Fresh.close(:ws_conn, 1000, "dunno")
:ok
@spec send(:gen_statem.server_ref(), Mint.WebSocket.frame()) :: :ok
Sends a WebSocket frame to the server.
pid
: The WebSocket connection process.frame
: The WebSocket frame to send.Example:
{:text, "hi!"}
Example
iex> Fresh.send(:ws_conn, {:text, "hi!"})
:ok
@spec start(binary(), module(), any(), [option()]) :: :gen_statem.start_ret()
Starts a WebSocket connection without linking process. Refer to start_link/4
for more information.
@spec start_link(binary(), module(), any(), [option()]) :: :gen_statem.start_ret()
Starts a WebSocket connection.
uri
: The URI to connect to.Example:
"wss://example.com/socket"
module
: The module that implementes the WebSocket client behaviour.Example:
Example.WebSocket
state
: The initial state to be passed to the module when it starts.Example:
%{}
opts
: A list of options to configure the WebSocket connection. Refer tooption/0
for available options.Example:
[name: {:local, :ws_conn}, headers: [{"Authorization", "Bearer token"}]]
Example
iex> Fresh.start_link("wss://example.com/socket", Example.WebSocket, %{}, name: {:local, :ws_conn})
{:ok, #PID<0.233.0>}