Transport
Cowboy transport
Wiregrid.Transport.Cowboy is an optional WebSocket handler. The host application supplies Cowboy. Wiregrid’s own mix.exs lists Cowboy only under only: :test, pinned to ~> 2.18.0 with Cowlib ~> 2.19.0 so OTP 26 can compile the suite. Production apps add the Cowboy version they run.
Authentication runs in init/2, before the upgrade. The session is created in websocket_init/1, so the Cowboy process is the session owner. On terminate, a live session is disconnected with reason :transport_closed.
Options
| Key | Default |
|---|---|
:instance | required |
:auth / :auth_fun | how the request becomes a user id |
:protocol | Wiregrid.Transport.Protocol.Term |
:origin_allowlist | []. A present Origin must match exactly |
:max_frame_size | max_websocket_frame_bytes (1,048,576) |
:idle_timeout | 60,000 ms, passed through to Cowboy |
:ack_strategy | :client or :transport |
:connect_opts | []. Allowed keys: :metadata, :status, :presence_metadata |
:auth_rate_limit | 30 |
:auth_window_ms | 60,000 |
:auth_rate_policy | :fixed_window |
:auth_rate_burst | the limit, used when the policy is :token_bucket |
:frame_rate_limit | 240 (range 1..100,000) |
:frame_window_ms | 60,000 (range 100..3,600,000) |
:frame_rate_policy | :token_bucket |
:frame_rate_burst | the frame limit |
:allow_permissive_authorizer | false. AllowAll is rejected unless this is true |
:command_handler | nil. A 2-arity function or a module with handle_command/2 |
Unknown keys fail validation and the handshake is rejected. A failed init returns HTTP 401, or 400 when the option list itself is unusable. :client ack strategy connects the session with ack_mode: :manual. :transport uses ack_mode: :transport and acknowledges only after the handler has encoded the outbound frame. JSON protocol forces text frames and delivery_format: :term. The term protocol uses binary frames and delivery_format: :encoded. A text frame on the term protocol is :binary_frames_required.
Pre-auth limiting is keyed by peer IP under the bucket :websocket_auth. Authenticated frames use the frame limiter. A limited frame returns {:error, nil, :rate_limited}. If the limiter itself is unavailable, the socket stops.
Handshake result
A new socket calls connect_resumable/4. A request that already carries a resume token calls resume_session/5. The first outbound message is {:ready, %{session_id:, resume_token:, restored:}}. Connect failure stops the socket with {:connect_failed, reason}.
Commands
Wiregrid.Transport.Command.dispatch/5 handles built-in commands before any extension. The command term is bounded (depth and size) and must fit in max_websocket_frame_bytes. Publish-shaped commands have session_id injected from the socket. A client-supplied :session_id is :transport_session_override.
{:subscribe, topic}and{:subscribe, topic, context}{:unsubscribe, topic}{:publish, topic, event, opts},{:publish_room, room, event, opts},{:dispatch, targets, event, opts}{:send_user, user_id, event, opts},{:send_session, target, event, opts}{:presence, status}and{:presence, status, metadata}{:watch_presence, user_id},{:unwatch_presence, user_id}{:join_room, room},{:join_room, room, opts},{:leave_room, room}{:room_metadata, room, metadata, opts},{:room_ttl, room, ttl}{:typing, topic, opts},{:activity, topic, kind, value, opts}{:receipt, receipt, opts},{:signal, room, kind, payload, opts}{:sync_topology, topology, opts}{:request_session, target, event, opts},{:reply, envelope, event, opts}{:replay, stream, opts}bound to the current session{:history, topic, opts}with:cursorand:limit(default 50) viaread_history/5{:ack, delivery_id},{:ack_many, delivery_ids}{:ping, nonce}returns{:pong, nonce}
Unknown commands go to command_handler. The extension receives the command and a map with instance, session_id, and user_id. Auth headers, resume tokens, and the Cowboy request are not included. A crash or throw is {:error, :command_handler_failed}. With no handler, the result is {:error, :unknown_command}. LFE can generate a fixed grammar with wiregrid_macros:defcompiled-command-handler.
Inbound frames may be {:request, request_id, command} or a bare command. The reply is {:response, request_id, result}. Outbound deliveries are {:event, envelope}. Encode failure stops the socket with :outbound_encode_failed. Oversized binary frames stop it with :frame_too_large.