WebSocket Relay
El middleware WebSocket relay actualiza conexiones HTTP a WebSocket y retransmite mensajes a un proceso destino.
Cómo Funciona
- El manejador HTTP establece el header
X-WS-Relaycon el PID del proceso destino - El middleware actualiza la conexión a WebSocket
- El relay se adjunta al proceso destino y lo monitorea
- Los mensajes fluyen bidireccionalmente entre cliente y proceso
Semántica de Procesos
Las conexiones WebSocket son procesos completos con su propio PID. Se integran con el sistema de procesos:
- Direccionable - Cualquier proceso puede enviar mensajes a un PID de WebSocket
- Monitoreable - Los procesos pueden monitorear conexiones WebSocket para eventos de salida
- Enlazable - Las conexiones WebSocket pueden enlazarse a otros procesos
- Eventos EXIT - Cuando la conexión se cierra, los monitores reciben notificaciones de salida
-- Monitorear una conexión WebSocket desde otro proceso
process.monitor(websocket_pid)
-- Enviar mensaje a cliente WebSocket desde cualquier proceso
process.send(websocket_pid, "ws.send", {type = "text", data = "hello"})
Transferencia de Conexión
Las conexiones pueden transferirse a un proceso diferente enviando un mensaje de control:
process.send(websocket_pid, "ws.control", {
target_pid = new_process_pid,
message_topic = "ws.message"
})
Configuración
Agregar como middleware post-match en un router:
- name: ws_router
kind: http.router
meta:
server: gateway
prefix: /ws
post_middleware:
- websocket_relay
post_options:
wsrelay.allowed.origins: "https://app.example.com"
| Opción | Descripción |
|---|---|
wsrelay.allowed.origins |
Orígenes permitidos separados por coma |
Configuración del Handler
El manejador HTTP genera un proceso y configura el relay:
local http = require("http")
local json = require("json")
local function handler()
local req = http.request()
local res = http.response()
-- Generar proceso manejador
local pid = process.spawn("app.ws:handler", "app:processes")
-- Configurar relay
res:header("X-WS-Relay", json.encode({
target_pid = tostring(pid),
message_topic = "ws.message",
heartbeat_interval = "30s",
metadata = {
user_id = req:query("user_id")
}
}))
end
Campos de Configuración del Relay
| Campo | Tipo | Por Defecto | Descripción |
|---|---|---|---|
target_pid |
string | requerido | PID del proceso que recibe mensajes |
message_topic |
string | ws.message |
Tópico para mensajes del cliente |
heartbeat_interval |
duration | - | Frecuencia de heartbeat (ej. 30s) |
metadata |
object | - | Adjunto a todos los mensajes |
Tópicos de Mensajes
El relay envía estos mensajes al proceso destino:
| Tópico | Cuándo | Payload |
|---|---|---|
ws.join |
Cliente conecta | client_pid, metadata |
ws.message |
Cliente envía mensaje | client_pid, type, data, metadata |
ws.heartbeat |
Periódico (si configurado) | client_pid, uptime, message_count |
ws.leave |
Cliente desconecta | client_pid, reason, metadata |
Recibir Mensajes
local json = require("json")
local function handler()
local inbox = process.inbox()
while true do
local msg, ok = inbox:receive()
if not ok then break end
local topic = msg:topic()
local data = msg:payload():data()
if topic == "ws.join" then
-- Cliente conectado
local client_pid = data.client_pid
elseif topic == "ws.message" then
-- Manejar mensaje del cliente
local content = json.decode(data.data)
handle_message(data.client_pid, content)
elseif topic == "ws.leave" then
-- Cliente desconectado
cleanup(data.client_pid)
end
end
end
Enviar al Cliente
Envíe mensajes de vuelta usando el PID del cliente:
-- Enviar mensaje de texto
process.send(client_pid, "ws.send", {
type = "text",
data = json.encode({event = "update", value = 42})
})
-- Enviar binario
process.send(client_pid, "ws.send", {
type = "binary",
data = binary_content
})
-- Cerrar conexión
process.send(client_pid, "ws.close", {
code = 1000,
reason = "Sesión terminada"
})
Broadcasting
Rastree PIDs de clientes para hacer broadcast a múltiples clientes:
local clients = {}
-- Al unirse
clients[client_pid] = true
-- Al salir
clients[client_pid] = nil
-- Broadcast
local function broadcast(message)
local data = json.encode(message)
for pid, _ in pairs(clients) do
process.send(pid, "ws.send", {type = "text", data = data})
end
end
Ver También
- Middleware - Configuración de middleware
- Procesos - Mensajería de procesos
- Cliente WebSocket - Conexiones WebSocket salientes