Phoenix v1.3.0 Phoenix.Socket behaviour View Source

Defines a socket and its state.

Phoenix.Socket is used as a module for establishing and maintaining the socket state via the Phoenix.Socket struct.

Once connected to a socket, incoming and outgoing events are routed to channels. The incoming client data is routed to channels via transports. It is the responsibility of the socket to tie transports and channels together.

By default, Phoenix supports both websockets and longpoll transports. For example:

transport :websocket, Phoenix.Transports.WebSocket

The command above means incoming socket connections can be made via the WebSocket transport. Events are routed by topic to channels:

channel "room:lobby", MyApp.LobbyChannel

See Phoenix.Channel for more information on channels. Check each transport module to find the options specific to each transport.

Socket Behaviour

Socket handlers are mounted in Endpoints and must define two callbacks:

  • connect/2 - receives the socket params and authenticates the connection. Must return a Phoenix.Socket struct, often with custom assigns.
  • id/1 - receives the socket returned by connect/2 and returns the id of this connection as a string. The id is used to identify socket connections, often to a particular user, allowing us to force disconnections. For sockets requiring no authentication, nil can be returned.

Examples

defmodule MyApp.UserSocket do
  use Phoenix.Socket

  transport :websocket, Phoenix.Transports.WebSocket
  channel "room:*", MyApp.RoomChannel

  def connect(params, socket) do
    {:ok, assign(socket, :user_id, params["user_id"])}
  end

  def id(socket), do: "users_socket:#{socket.assigns.user_id}"
end

# Disconnect all user's socket connections and their multiplexed channels
MyApp.Endpoint.broadcast("users_socket:" <> user.id, "disconnect", %{})

Socket Fields

  • id - The string id of the socket
  • assigns - The map of socket assigns, default: %{}
  • channel - The current channel module
  • channel_pid - The channel pid
  • endpoint - The endpoint module where this socket originated, for example: MyApp.Endpoint
  • handler - The socket module where this socket originated, for example: MyApp.UserSocket
  • joined - If the socket has effectively joined the channel
  • pubsub_server - The registered name of the socket’s pubsub server
  • join_ref - The ref sent by the client when joining
  • ref - The latest ref sent by the client
  • topic - The string topic, for example "room:123"
  • transport - The socket’s transport, for example: Phoenix.Transports.WebSocket
  • transport_pid - The pid of the socket’s transport process
  • transport_name - The socket’s transport, for example: :websocket
  • serializer - The serializer for socket messages, for example: Phoenix.Transports.WebSocketSerializer
  • vsn - The protocol version of the client, for example: “2.0.0”

Custom transports

See the Phoenix.Socket.Transport documentation for more information on writing your own transports.

Link to this section Summary

Functions

Adds key/value pair to socket assigns

Defines a channel matching the given topic and transports

Defines a transport with configuration

Callbacks

Receives the socket params and authenticates the connection

Identifies the socket connection

Link to this section Types

Link to this type t() View Source
t() :: %Phoenix.Socket{assigns: map(), channel: atom(), channel_pid: pid(), endpoint: atom(), handler: atom(), id: nil, join_ref: term(), joined: boolean(), private: %{}, pubsub_server: atom(), ref: term(), serializer: atom(), topic: String.t(), transport: atom(), transport_name: atom(), transport_pid: pid(), vsn: term()}

Link to this section Functions

Link to this function assign(socket, key, value) View Source

Adds key/value pair to socket assigns.

Examples

iex> socket.assigns[:token]
nil
iex> socket = assign(socket, :token, "bar")
iex> socket.assigns[:token]
"bar"
Link to this macro channel(topic_pattern, module, opts \\ []) View Source (macro)

Defines a channel matching the given topic and transports.

  • topic_pattern - The string pattern, for example “room:“, “users:”, “system”
  • module - The channel module handler, for example MyApp.RoomChannel
  • opts - The optional list of options, see below

Options

  • :via - the transport adapters to accept on this channel. Defaults [:websocket, :longpoll]
  • :assigns - the map of socket assigns to merge into the socket on join.

Examples

channel "topic1:*", MyChannel
channel "topic2:*", MyChannel, via: [:websocket]
channel "topic",    MyChannel, via: [:longpoll]

Topic Patterns

The channel macro accepts topic patterns in two flavors. A splat argument can be provided as the last character to indicate a “topic:subtopic” match. If a plain string is provided, only that topic will match the channel handler. Most use-cases will use the “topic:*” pattern to allow more versatile topic scoping.

See Phoenix.Channel for more information

Link to this macro transport(name, module, config \\ []) View Source (macro)

Defines a transport with configuration.

Examples

# customize default `:websocket` transport options
transport :websocket, Phoenix.Transports.WebSocket,
  timeout: 10_000

# define separate transport, using websocket handler
transport :websocket_slow_clients, Phoenix.Transports.WebSocket,
  timeout: 60_000

Link to this section Callbacks

Link to this callback connect(params, arg1) View Source
connect(params :: map(), Phoenix.Socket.t()) ::
  {:ok, Phoenix.Socket.t()} |
  :error

Receives the socket params and authenticates the connection.

Socket params and assigns

Socket params are passed from the client and can be used to verify and authenticate a user. After verification, you can put default assigns into the socket that will be set for all channels, ie

{:ok, assign(socket, :user_id, verified_user_id)}

To deny connection, return :error.

See Phoenix.Token documentation for examples in performing token verification on connect.

Identifies the socket connection.

Socket IDs are topics that allow you to identify all sockets for a given user:

def id(socket), do: "users_socket:#{socket.assigns.user_id}"

Would allow you to broadcast a “disconnect” event and terminate all active sockets and channels for a given user:

MyApp.Endpoint.broadcast("users_socket:" <> user.id, "disconnect", %{})

Returning nil makes this socket anonymous.