The websocket module is experimental.
local websocket = require('websocket')
local ws = websocket.new()

local text = nil
local buf = byte_span.new(1024 * 10)
local bytes_read, status
    bytes_read, status = ws:read_some(buf)
    text = byte_span.append(text, buf:slice(1, bytes_read))
until status ~= 'partial'


new() → websocket

new(socket: ip.tcp.socket|tls.socket, host: string, request_target: string[, extra_headers: { [string]: string }]) (1)
new(socket: http.socket, request: http.request[, extra_headers: { [string]: string }]) (2)
1 Client mode.
2 Server mode.


Previous socket object is moved-from and becomes an invalid object. Then, the WebSocket handshake is sent (client or server). When the handshake is complete, the websocket object is returned. If an error happens, connection is closed ungracefully and an error is thrown.

You can send extra headers in the opening handshake through the extra_headers parameter. Optional headers such as "origin" aren’t added by default. A list of common headers that might be of interest follows:


Compare the "origin" to the "host" to block malicious scripts coming from web browsers.


Authentication token.


If present, this value indicates one or more comma-separated subprotocols the client wishes to speak, ordered by preference.

On client mode, new() returns a second object representing the headers sent by the server.

is_websocket_upgrade(req: http.request) → boolean

Returns whether req is a WebSocket upgrade request.

write(self, data: string|byte_span[, type: string])

Send a buffer as a complete message.

type might be one of the following:


UTF-8 text.


Binary data.


The default. It means "text" if data is a string and "binary" otherwise.

read_some(self, buffer: byte_span) → integer, string

Reads some data into buffer. Returns the number of bytes written to buffer + a string with one of the following values:


More message pieces are expected.


Message is done and should be interpreted as binary.


Message is done and should be interpreted as text.

close(self[, code: integer = 1005[, reason: string]])

This composed operation sends the close frame if it hasn’t already been sent, then reads and discards frames until receiving a close frame. Finally it invokes the teardown operation to shut down the underlying connection.