Phoenix v1.3.0 Phoenix.Socket.Transport behaviour View Source

API for building transports.

This module describes what is required to build a Phoenix transport. The transport sits between the socket and channels, forwarding client messages to channels and vice-versa.

A transport is responsible for:

  • Implementing the transport behaviour
  • Establishing the socket connection
  • Handling of incoming messages
  • Handling of outgoing messages
  • Managing channels
  • Providing secure defaults

The transport behaviour

The transport requires one function:

  • default_config/0 - returns the default transport configuration to be merged when the transport is declared in the socket module

Socket connections

Once a connection is established, the transport is responsible for invoking the Phoenix.Socket.connect/2 callback and acting accordingly. Once connected, the transport should request the Phoenix.Socket.id/1 and subscribe to the topic if one exists. On subscribed, the transport must be able to handle “disconnect” broadcasts on the given id topic.

The connect/6 function in this module can be used as a convenience or a documentation on such steps.

Incoming messages

Incoming messages are encoded in whatever way the transport chooses. Those messages must be decoded in the transport into a Phoenix.Socket.Message before being forwarded to a channel.

Most of those messages are user messages except:

  • “heartbeat” events in the “phoenix” topic - should just emit an OK reply
  • “phx_join” on any topic - should join the topic
  • “phx_leave” on any topic - should leave the topic

The function dispatch/3 can be used to handle these messages.

Outgoing messages

Channels can send two types of message back to a transport: Phoenix.Socket.Message and Phoenix.Socket.Reply. Those messages are encoded in the channel into a format defined by the transport. That’s why transports are required to pass a serializer that abides to the behaviour described in Phoenix.Transports.Serializer.

Managing channel exits

Because channels are spawned from the transport process, transports must trap exits and correctly handle the {:EXIT, _, _} messages arriving from channels, relaying the proper response to the client.

The "phx_error" event is sent by the transport when a channel exits, and represents the channel terminating against its will. The on_exit_message/3 function aids in constructing the "phx_error" message.

For graceful exits, the channel will notify the transort it is gracefully terminating via the following message:

{:graceful_exit, channel_pid, %Phoenix.Socket.Message{}}

The %Phoenix.Socket.Message{} is the leave message for the transport to relay to the client.

Duplicate Join Subscriptions

For a given topic, the client may only establish a single channel subscription. When attempting to create a duplicate subscription, dispatch/3 will close the existing channel, log a warning, and spawn a new channel for the topic. When sending the "phx_close" event from the closed channel, the message will contain the ref the client sent when joining. This allows the client to uniquely identify "phx_close" and "phx_error" messages when force-closing a channel on duplicate joins.

Security

This module also provides functions to enable a secure environment on transports that, at some point, have access to a Plug.Conn.

The functionality provided by this module helps in performing “origin” header checks and ensuring only SSL connections are allowed.

Remote Client

Channels can reply, synchronously, to any handle_in/3 event. To match pushes with replies, clients must include a unique ref with every message and the channel server will reply with a matching ref where the client can pick up the callback for the matching reply.

Phoenix includes a JavaScript client for WebSocket and Longpolling support using JSON encodings.

Clients can be implemented for other protocols and encodings by abiding by the Phoenix.Socket.Message format.

Protocol Versioning

Clients are expected to send the Channel Transport protocol version that they expect to be talking to. The version can be retrieved on the server from Phoenix.Channel.Transport.protocol_version/0. If no version is provided, the Transport adapters should default to assume a "1.0.0" version number. See web/static/js/phoenix.js for an example transport client implementation.

Link to this section Summary

Functions

Checks the origin request header against the list of allowed origins

Forces SSL in the socket connection

Returns the message to be relayed when a channel exits

Returns the Channel Transport protocol version

Logs the transport request

Callbacks

Provides a keyword list of default configuration for socket transports

Link to this section Functions

Link to this function check_origin(conn, handler, endpoint, opts, sender \\ &Plug.Conn.send_resp/1) View Source

Checks the origin request header against the list of allowed origins.

Should be called by transports before connecting when appropriate. If the origin header matches the allowed origins, no origin header was sent or no origin was configured, it will return the given connection.

Otherwise a 403 Forbidden response will be sent and the connection halted. It is a noop if the connection has been halted.

Link to this function connect(endpoint, handler, transport_name, transport, serializer_config, params) View Source

Handles the socket connection.

It builds a new Phoenix.Socket, invokes the handler connect/2 callback and returns the result.

If the connection was successful, generates Phoenix.PubSub topic from the id/1 callback.

Link to this function dispatch(msg, channels, socket) View Source

Dispatches Phoenix.Socket.Message to a channel.

All serialized, remote client messages should be deserialized and forwarded through this function by adapters.

The following returns must be handled by transports:

  • :noreply - Nothing to be done by the transport
  • {:reply, reply} - The reply to be sent to the client
  • {:joined, channel_pid, reply} - The channel was joined and the reply must be sent as result
  • {:error, reason, reply} - An error occurred and the reply must be sent as result

Parameter filtering on join

When logging parameters, Phoenix can filter out sensitive parameters such as passwords and tokens. Parameters to be filtered can be added via the :filter_parameters option:

config :phoenix, :filter_parameters, ["password", "secret"]

With the configuration above, Phoenix will filter any parameter that contains the terms password or secret. The match is case sensitive.

Phoenix’s default is ["password"].

Link to this function force_ssl(conn, socket, endpoint, opts) View Source

Forces SSL in the socket connection.

Uses the endpoint configuration to decide so. It is a noop if the connection has been halted.

Link to this function on_exit_message(topic, join_ref, reason) View Source

Returns the message to be relayed when a channel exits.

Returns the Channel Transport protocol version.

Link to this function transport_log(conn, level) View Source

Logs the transport request.

Available for transports that generate a connection.

Link to this section Callbacks

Link to this callback default_config() View Source
default_config() :: Keyword.t()

Provides a keyword list of default configuration for socket transports.