WebSockets¶
WebSockets permiten la comunicación bidireccional entre un cliente y un servidor. A diferencia de HTTP, que tiene un patrón de solicitud y respuesta, los pares de WebSocket pueden enviar una cantidad arbitraria de mensajes en cualquier dirección. La API WebSocket de Vapor te permite crear tanto clientes como servidores que manejan mensajes de forma asincrónica.
Servidor¶
Los endpoints de WebSocket se pueden agregar a tu aplicación Vapor existente mediante la API de enrutamiento. Usa el método webSocket
como usarías get
o post
.
app.webSocket("echo") { req, ws in
// Connected WebSocket.
print(ws)
}
Las rutas de WebSocket se pueden agrupar y proteger mediante middleware como las rutas normales.
Además de aceptar la solicitud HTTP entrante, los controladores de WebSocket aceptan la conexión WebSocket recién establecida. Consulta a continuación para obtener más información sobre el uso de este WebSocket para enviar y leer mensajes.
Cliente¶
Para conectarse a un endpoint remoto de WebSocket, use WebSocket.connect
.
WebSocket.connect(to: "ws://echo.websocket.org", on: eventLoop) { ws in
// WebSocket conectado.
print(ws)
}
El método connect
devuelve un futuro que se completa cuando se establece la conexión. Una vez conectado, se llamará al closure proporcionado con el WebSocket recién conectado. Mira más información a continuación sobre el uso de este WebSocket para enviar y leer mensajes.
Mensajes¶
La clase WebSocket
tiene métodos para enviar y recibir mensajes, así como para escuchar eventos como el closure. Los WebSockets pueden transmitir datos a través de dos protocolos: texto y binario. Los mensajes de texto se interpretan como cadenas UTF-8, mientras que los datos binarios se interpretan como una matriz de bytes.
Envío¶
Los mensajes se pueden enviar utilizando el método send
de WebSocket.
ws.send("Hello, world")
Pasar una String
a este método da como resultado el envío de un mensaje de texto. Los mensajes binarios se pueden enviar pasando un [UInt8]
.
ws.send([1, 2, 3])
El envío de mensajes es asincrónico. Puede proporcionar un EventLoopPromise
al método de envío para recibir una notificación cuando el mensaje haya terminado de enviarse o falle en el envío.
let promise = eventLoop.makePromise(of: Void.self)
ws.send(..., promise: promise)
promise.futureResult.whenComplete { result in
// Envío exitoso o fallido.
}
Si usas async
/await
, puedes usar await
para esperar a que se complete la operación asincrónica
try await ws.send(...)
Recepción¶
Los mensajes entrantes se manejan a través de los callbacks onText
y onBinary
.
ws.onText { ws, text in
// Cadena recibida por este WebSocket.
print(text)
}
ws.onBinary { ws, binary in
// [UInt8] recibido por este WebSocket.
print(binary)
}
El propio WebSocket se proporciona como el primer parámetro de estos callbacks para evitar ciclos de referencia. Usa esta referencia para realizar una acción en el WebSocket después de recibir datos. Por ejemplo, para enviar una respuesta:
// Se hace eco de los mensajes recibidos.
ws.onText { ws, text in
ws.send(text)
}
Cierre¶
Para cerrar un WebSocket, llama al método close
.
ws.close()
Este método devuelve un futuro que se completará cuando el WebSocket se haya cerrado. Al igual que send
, también puede pasar una promesa a este método.
ws.close(promise: nil)
O await
si usas async
/await
:
try await ws.close()
Para recibir una notificación cuando el par cierra la conexión, utiliza onClose
. Este futuro se completará cuando el cliente o el servidor cierren el WebSocket.
ws.onClose.whenComplete { result in
// Cierre exitoso o fallido.
}
La propiedad closeCode
se establece cuando el WebSocket se cierra. Esto se puede utilizar para determinar por qué el par cerró la conexión.
Ping / Pong¶
El cliente y el servidor envían automáticamente mensajes de ping y pong para mantener activas las conexiones WebSocket. Su aplicación puede escuchar estos eventos mediante los callbacks onPing
y onPong
.
ws.onPing { ws in
// Se recibió ping.
}
ws.onPong { ws in
// Se recibió pong.
}