Ir al contenido

Cliente WebSocket

Cliente WebSocket para comunicación bidireccional en tiempo real con servidores.

local websocket = require("websocket")
local client, err = websocket.connect("wss://api.example.com/ws")
if err then
return nil, err
end
local client, err = websocket.connect("wss://api.example.com/ws", {
headers = {
["Authorization"] = "Bearer " .. token
},
protocols = {"graphql-ws"},
dial_timeout = "10s",
read_timeout = "30s",
compression = websocket.COMPRESSION.CONTEXT_TAKEOVER
})
ParámetroTipoDescripción
urlstringURL WebSocket (ws:// o wss://)
optionstableOpciones de conexión (opcional)

Devuelve: Client, error

OpcionTipoDescripción
headerstableCabeceras HTTP para handshake
protocolstableSubprotocolos WebSocket
dial_timeoutnumber/stringTimeout de conexión (ms o “5s”)
read_timeoutnumber/stringTimeout de lectura
write_timeoutnumber/stringTimeout de escritura
compressionnumberModo de compresion (ver Constantes)
compression_thresholdnumberTamano minimo para comprimir (0-100MB)
read_limitnumberTamano maximo de mensaje (0-128MB)
channel_capacitynumberBuffer de canal de recepcion (1-10000)

Formato de timeout: Numeros son milisegundos, strings usan formato de duración Go (“5s”, “1m”).

local ok, err = client:send("Hello, Server!")
if err then
return nil, err
end
-- Enviar JSON
client:send(json.encode({
type = "subscribe",
channel = "orders"
}))
client:send(binary_data, websocket.BINARY)
ParámetroTipoDescripción
datastringContenido del mensaje
typenumberwebsocket.TEXT (1) o websocket.BINARY (2)

Cede hasta que el mensaje se envía.

Devuelve: boolean, error

client:ping()

Cede hasta que el ping se envía.

Devuelve: boolean, error

El método channel() devuelve un canal para recibir mensajes. receive() es un alias de channel(). Funciona con channel.select para multiplexado.

local ch = client:channel()
local msg, ok = ch:receive()
if ok then
print("Type:", msg.type) -- "text" o "binary"
print("Data:", msg.data)
end
local ch = client:channel()
while true do
local msg, ok = ch:receive()
if not ok then
break -- Conexión cerrada
end
if msg.type == "text" then
local data = json.decode(msg.data)
handle_message(data)
end
end
local ch = client:channel()
local timeout = time.after("30s")
while true do
local r = channel.select {
ch:case_receive(),
timeout:case_receive()
}
if r.channel == timeout then
client:ping() -- Keep-alive
timeout = time.after("30s")
else
local data = json.decode(r.value.data)
process(data)
end
end
CampoTipoDescripción
typestring"text" o "binary"
datastring?Contenido del mensaje (nil para tipos de payload desconocidos)
-- Cierre normal (código 1000)
client:close()
-- Con código y razon
client:close(websocket.CLOSE_CODES.NORMAL, "Session ended")
-- Cierre de error
client:close(websocket.CLOSE_CODES.INTERNAL_ERROR, "Processing failed")
ParámetroTipoDescripción
codenumberCódigo de cierre (1000-4999), predeterminado 1000
reasonstringRazon de cierre (opcional)

Devuelve: boolean, error

-- Numerico (para enviar)
websocket.TEXT -- 1
websocket.BINARY -- 2
-- String (campo type de mensaje recibido)
websocket.TYPE_TEXT -- "text"
websocket.TYPE_BINARY -- "binary"
websocket.TYPE_PING -- "ping"
websocket.TYPE_PONG -- "pong"
websocket.TYPE_CLOSE -- "close"
websocket.COMPRESSION.DISABLED -- 0 (sin compresion)
websocket.COMPRESSION.CONTEXT_TAKEOVER -- 1 (ventana deslizante)
websocket.COMPRESSION.NO_CONTEXT -- 2 (por mensaje)
ConstanteCódigoDescripción
NORMAL1000Cierre normal
GOING_AWAY1001Servidor apagandose
PROTOCOL_ERROR1002Error de protocolo
UNSUPPORTED_DATA1003Tipo de datos no soportado
RESERVED1004Reservado
NO_STATUS1005Sin estado recibido
ABNORMAL_CLOSURE1006Conexión perdida
INVALID_PAYLOAD1007Payload de frame invalido
POLICY_VIOLATION1008Violacion de politica
MESSAGE_TOO_BIG1009Mensaje muy grande
MANDATORY_EXTENSION1010Extension requerida no negociada
INTERNAL_ERROR1011Error del servidor
SERVICE_RESTART1012Servidor reiniciando
TRY_AGAIN_LATER1013Servidor sobrecargado
BAD_GATEWAY1014Error de gateway
TLS_HANDSHAKE1015Fallo de handshake TLS
client:close(websocket.CLOSE_CODES.NORMAL, "Done")
local function connect_chat(room_id, on_message)
local client, err = websocket.connect("wss://chat.example.com/ws", {
headers = {["Authorization"] = "Bearer " .. token}
})
if err then
return nil, err
end
-- Unirse a sala
client:send(json.encode({
type = "join",
room = room_id
}))
-- Bucle de mensajes
local ch = client:channel()
while true do
local msg, ok = ch:receive()
if not ok then break end
local data = json.decode(msg.data)
on_message(data)
end
client:close()
end
local client = websocket.connect("wss://stream.example.com/prices")
client:send(json.encode({
action = "subscribe",
symbols = {"BTC-USD", "ETH-USD"}
}))
local ch = client:channel()
local heartbeat = time.after("30s")
while true do
local r = channel.select {
ch:case_receive(),
heartbeat:case_receive()
}
if r.channel == heartbeat then
client:ping()
heartbeat = time.after("30s")
elseif not r.ok then
break -- Conexión cerrada
else
local price = json.decode(r.value.data)
update_price(price.symbol, price.value)
end
end
client:close()

Las conexiones WebSocket estan sujetas a evaluacion de politica de seguridad.

AccionRecursoDescripción
websocket.connect-Permitir/denegar conexiones WebSocket
websocket.connect.urlURLPermitir/denegar conexiones a URLs especificas

Consulte Modelo de Seguridad para configuración de politicas.

CondiciónTipoReintentable
Conexiones deshabilitadaserrors.PERMISSION_DENIEDno
URL no permitidaerrors.PERMISSION_DENIEDno
Sin contextoerrors.INTERNALno
Conexión fallidaerrors.INTERNALsi
ID de conexión invalidoerrors.INTERNALno
local client, err = websocket.connect(url)
if err then
if errors.is(err, errors.PERMISSION_DENIED) then
print("Acceso denegado:", err:message())
elseif err:retryable() then
print("Error temporal:", err:message())
end
return nil, err
end

Consulte Manejo de Errores para trabajar con errores.