Phoenix v1.2.1 Phoenix.Socket.Transport behaviour

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 two functions:

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

  • handlers/0 - returns a map of handlers. For example, if the transport can be run cowboy, it just need to specify the appropriate cowboy handler

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 by:

  • “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 help with handling of such messages.

Outgoing messages

Channels can send two types of messages 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 channels

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 following events are sent by the transport when a channel exits:

  • "phx_close" - The channel has exited gracefully
  • "phx_error" - The channel has crashed

The on_exit_message/3 function aids in constructing these messages.

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 form 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 help with doing “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 and pick up the callback for the matching reply.

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

However, a client 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.

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 exists

Returns the Channel Transport protocol version

Logs the transport request

Callbacks

Provides a keyword list of default configuration for socket transports

Functions

check_origin(conn, handler, endpoint, opts, sender \\ &Plug.Conn.send_resp/1)

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 otherwise a 403 Forbidden response will be sent and the connection halted. It is a noop if the connection has been halted.

connect(endpoint, handler, transport_name, transport, serializer, params)

Handles the socket connection.

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

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

dispatch(msg, channels, socket)

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 happened and the reply must be sent as result

Parameters filtering on join

When logging parameters, Phoenix can filter out sensitive parameters in the logs, such as passwords, tokens and what not. 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"].

force_ssl(conn, socket, endpoint, opts)

Forces SSL in the socket connection.

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

on_exit_message(topic, reason)

Returns the message to be relayed when a channel exists.

on_exit_message(topic, join_ref, reason)
protocol_version()

Returns the Channel Transport protocol version.

transport_log(conn, level)

Logs the transport request.

Available for transports that generate a connection.

Callbacks

default_config()

Specs

default_config :: Keyword.t

Provides a keyword list of default configuration for socket transports.