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

http.websocket

import http.websocket

http lifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelled http.websocket.* needs import http.websocket.

WebSocket (RFC 6455), both ends of it.

accept() upgrades an inbound request, connect() opens an outbound connection, and WebSocket is the resulting full-duplex channel. Message is one complete message, reassembled from however many frames carried it, and the CLOSE_* constants are the status codes a close may carry.

Constants

OPCODE_CONTINUATION

http.websocket.OPCODE_CONTINUATION = 0

Continuation frame. @type int

OPCODE_TEXT

http.websocket.OPCODE_TEXT = 1

Text frame. @type int

OPCODE_BINARY

http.websocket.OPCODE_BINARY = 2

Binary frame. @type int

OPCODE_CLOSE

http.websocket.OPCODE_CLOSE = 8

Close frame. @type int

OPCODE_PING

http.websocket.OPCODE_PING = 9

Ping frame. @type int

OPCODE_PONG

http.websocket.OPCODE_PONG = 10

Pong frame. @type int

CLOSE_NORMAL

http.websocket.CLOSE_NORMAL = 1000

Normal closure. @type int

CLOSE_GOING_AWAY

http.websocket.CLOSE_GOING_AWAY = 1001

The endpoint is going away. @type int

CLOSE_PROTOCOL_ERROR

http.websocket.CLOSE_PROTOCOL_ERROR = 1002

A protocol error was detected. @type int

CLOSE_UNSUPPORTED

http.websocket.CLOSE_UNSUPPORTED = 1003

A message of a kind this endpoint cannot accept. @type int

CLOSE_INVALID_PAYLOAD

http.websocket.CLOSE_INVALID_PAYLOAD = 1007

A text message that was not valid UTF-8. @type int

CLOSE_POLICY_VIOLATION

http.websocket.CLOSE_POLICY_VIOLATION = 1008

A message that violates a policy. @type int

CLOSE_TOO_LARGE

http.websocket.CLOSE_TOO_LARGE = 1009

A message too large to process. @type int

CLOSE_INTERNAL_ERROR

http.websocket.CLOSE_INTERNAL_ERROR = 1011

An unexpected condition on the server. @type int

Functions

accept_key()

http.websocket.accept_key(key: string) -> string

The value a server must return in Sec-WebSocket-Accept for a given client key.

Parameters

  • key (string) — the client’s Sec-WebSocket-Key

Returns string

is_handshake()

http.websocket.is_handshake(request) -> bool

Whether request is a well-formed WebSocket handshake.

Parameters

  • request (HttpRequest)

Returns bool

accept()

http.websocket.accept(request, response, options: ?dict) -> WebSocket

Completes a WebSocket handshake and takes over the connection.

Call this from an ordinary route handler. It writes the 101 response itself and hands back a WebSocket; the server will not write anything more on that connection afterwards.

server.get('/ws', @(request, response) {
  var socket = websocket.accept(request, response)
  # ... talk to the socket from here
})

Parameters

  • request (HttpRequest)
  • response (HttpResponse)
  • options (?dict) — protocols (the subprotocols this server supports, most preferred first), max_message_size

Returns WebSocket

Raises HttpError if the request is not a WebSocket handshake, or arrived on a connection that cannot be taken over

connect()

http.websocket.connect(target: string, options: ?dict) -> WebSocket

Opens a WebSocket connection to target.

Parameters

  • target (string) — a ws:// or wss:// URL
  • options (?dict) — headers (extra request headers), protocols (subprotocols to offer), tls_config, connect_timeout, max_message_size

Returns WebSocket

Raises HttpError if the server does not complete the handshake

Classes

Message

class http.websocket.Message

One complete WebSocket message, with any fragmentation already reassembled.

  • printable — has a @to_string(), so echo and print() show something useful

Fields

FieldTypeDescription
opcodeintThe opcode of the message: OPCODE_TEXT, OPCODE_BINARY, OPCODE_CLOSE, OPCODE_PING or OPCODE_PONG.
databytesThe payload.

Constructor

http.websocket.Message(opcode, data)

Message.is_text()

http.websocket.Message.is_text() -> bool

Whether this is a text message.

Returns bool

Message.is_binary()

http.websocket.Message.is_binary() -> bool

Whether this is a binary message.

Returns bool

Message.is_close()

http.websocket.Message.is_close() -> bool

Whether this is a close frame, meaning the peer has begun the closing handshake.

Returns bool

Message.text()

http.websocket.Message.text() -> string

The payload decoded as UTF-8 text.

Returns string

Message.close_code()

http.websocket.Message.close_code() -> ?number

The close code carried by a close frame, or nil when the frame carried no code (which RFC 6455 §7.1.5 says to read as 1005, “no status received”).

Returns ?number

Message.close_reason()

http.websocket.Message.close_reason() -> string

The human-readable reason carried by a close frame.

Returns string

Message.to_string()

http.websocket.Message.to_string()

WebSocket

class http.WebSocket

An open WebSocket connection (RFC 6455).

Created by accept() on the server side or connect() on the client side, never directly.

server.get('/ws', @(request, response) {
  var socket = websocket.accept(request, response)

  while socket.is_open() {
    var message = socket.receive()
    if message == nil {
      break
    }
    socket.send('you said: ' + message.text())
  }
})

Ping frames are answered automatically, and a close frame from the peer is answered and then reported to the caller, so the closing handshake completes without the application having to know the rules.

  • printable — has a @to_string(), so echo and print() show something useful

Fields

FieldTypeDescription
is_clientboolWhether this endpoint is the client, and so must mask every frame it sends.
protocol?stringThe subprotocol negotiated during the handshake, or nil.
max_message_sizenumberThe largest message this endpoint will assemble, in bytes.

Constructor

http.WebSocket(connection, is_client, protocol)

WebSocket.is_open()

http.WebSocket.is_open() -> bool

Whether the connection is still open.

Returns bool

WebSocket.connection()

http.WebSocket.connection() -> Connection

The underlying transport, for anything this class does not expose - a read timeout, the peer’s address, its certificate.

Returns Connection

WebSocket.send()

http.WebSocket.send(text: string)

Sends a text message.

Parameters

  • text (string)

WebSocket.send_binary()

http.WebSocket.send_binary(data)

Sends a binary message.

Parameters

  • data (bytes)

WebSocket.ping()

http.WebSocket.ping(data)

Sends a ping. A conforming peer answers with a pong carrying the same payload, which is how an idle connection is kept alive through a NAT or a proxy that would otherwise time it out.

Parameters

  • data (?bytes) — at most 125 bytes

WebSocket.pong()

http.WebSocket.pong(data)

Sends a pong. Only needed to answer a ping this class did not answer for you, or as an unsolicited heartbeat.

Parameters

  • data (?bytes)

WebSocket.close()

http.WebSocket.close(code: ?number, reason: ?string)

Begins the closing handshake and closes the transport.

Parameters

  • code (?number) — a close code; defaults to CLOSE_NORMAL
  • reason (?string) — at most 123 bytes once encoded

WebSocket.receive()

http.WebSocket.receive() -> ?Message

Reads the next message, reassembling fragments and answering pings along the way.

Returns nil when the connection closes without a close frame. A close frame is returned as a message, and answered first, so the caller can see the code and reason the peer sent.

Returns ?Message

Raises ProtocolError if the peer violates the framing rules

WebSocket.to_string()

http.WebSocket.to_string()

2026, Richard Ore and Zuri contributors