Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

WebSocket

Acts as a WebSocket server (consumer — listens for connections) or client (publisher — connects to a target URL). As a consumer it receives frames; as a publisher it sends them.

URL format

# Consumer (listen):   ws://<bind-address>   or  wss://<bind-address>
# Publisher (connect):  ws://host[:port]/path  or  wss://host[:port]/path

A publisher takes ws:// (plain) and wss:// (TLS); its URL is the target server. For a consumer the URL is the listen address (e.g. ws://0.0.0.0:9000).

TLS and authentication

SideSettingEffect
Consumertls.required: true with tls.cert_file and tls.key_fileListens with TLS. On the command line a wss:// source sets tls.required.
Consumertls.ca_file in additionOnly clients with a certificate signed by that CA are accepted (mutual TLS).
Publishera wss:// URLConnects with TLS and checks the server certificate and host name against the public roots.
Publishertls.ca_fileTrusts that CA instead of the public roots.
Publishertls.cert_file and tls.key_filePresents a client certificate.
Consumerbasic_auth: [user, password]An upgrade request without these credentials gets 401.
Publisherbasic_auth: [user, password]Sends them as the Authorization header of the upgrade request.
Consumermax_connections: NAt most N connections at once; one more gets 503. Unset means no limit.

A publisher with tls.required: true and a ws:// URL is refused when the route starts.

A listener without basic_auth and without tls.ca_file accepts every client, so bind it to loopback or put a proxy in front. basic_auth without TLS sends the password in the clear. A client has 10 seconds to complete the TLS handshake and send its upgrade request. Behind TLS a connection over max_connections is closed before the handshake instead of getting a 503. On the command line: ?basic_auth=["user","password"]&max_connections=1000.

With TLS a request for a path other than path is closed after the upgrade; without TLS it is answered with 404.

Delivery

WebSocket has no acknowledgement. A publisher answers pings, drops frames the server sends and connects again after the server closed the connection; a batch that is being written at the moment the server goes away is lost. Connect, TLS and upgrade together may take 10 seconds. A send has no limit of its own: add the timeout middleware for a server that may stop reading.

A listener closes its connections when its route stops. A client that does not read its replies for 10 seconds is disconnected. A message the route rejects is not signalled to the client; only a reply is. A route with a websocket input is therefore at-most-once, and required_delivery: at_least_once refuses it.

Config (YAML / library)

The same settings as a route endpoint in a config file, or in Route.from_config / fromConfig. Every URL query parameter is a field of the same name under websocket:.

input:
  websocket: { url: "0.0.0.0:9000" }                # listen address
output:
  websocket: { url: "ws://localhost:9000/events" }  # target server

A TLS listener, and a publisher that trusts a private CA:

input:
  websocket:
    url: "0.0.0.0:9443"
    tls: { required: true, cert_file: /etc/mqb/server.pem, key_file: /etc/mqb/server.key }
output:
  websocket:
    url: "wss://feed.internal:9443/events"
    tls: { ca_file: /etc/mqb/ca.pem }

Examples

Listen for WebSocket frames and forward them to Kafka, continuous:

mqb copy \
  --from ws://0.0.0.0:9000 \
  --to kafka://kafka.local:9092?topic=ws-events

Listen with TLS:

mqb copy \
  --from 'wss://0.0.0.0:9443?tls={"cert_file":"/etc/mqb/server.pem","key_file":"/etc/mqb/server.key"}' \
  --to kafka://kafka.local:9092?topic=ws-events

Only accept a specific path:

mqb copy \
  --from ws://0.0.0.0:9000?path=/ingest \
  --to file:///data/ws.jsonl?format=json

Push a stream to a remote WebSocket server, continuous:

mqb copy \
  --from redis://localhost:6379?stream=events \
  --to wss://feed.example.com/socket

Key options

OptionPurpose
pathConsumer-only: only upgrade requests whose URI path matches exactly are delivered.
message_id_headerConsumer-only: handshake header to read the message ID from (default message-id).
execution_modeConsumer-only: auto (default), direct_only, or routed.
backlogConsumer-only: TCP listen backlog for the accept socket (default 4096).
tlsTLS configuration (object; set with a JSON literal ?tls={...}). See TLS and authentication.
basic_auth[user, password]: required by a consumer, sent by a publisher.
max_connectionsConsumer-only: most connections open at once (default: no limit).
routed_queue_capacityConsumer-only: queue capacity for the routed adapter (default 100).

Full field list: reference/websocket.md.