Wiregrid Plainwire · Manual 1.0

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

KeyDefault
:instancerequired
:auth / :auth_funhow the request becomes a user id
:protocolWiregrid.Transport.Protocol.Term
:origin_allowlist[]. A present Origin must match exactly
:max_frame_sizemax_websocket_frame_bytes (1,048,576)
:idle_timeout60,000 ms, passed through to Cowboy
:ack_strategy:client or :transport
:connect_opts[]. Allowed keys: :metadata, :status, :presence_metadata
:auth_rate_limit30
:auth_window_ms60,000
:auth_rate_policy:fixed_window
:auth_rate_burstthe limit, used when the policy is :token_bucket
:frame_rate_limit240 (range 1..100,000)
:frame_window_ms60,000 (range 100..3,600,000)
:frame_rate_policy:token_bucket
:frame_rate_burstthe frame limit
:allow_permissive_authorizerfalse. AllowAll is rejected unless this is true
:command_handlernil. 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.

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.

Wiregrid 1.0 · Plainwire · github.com/Plainwire-development/Wiregrid