Websockets
Nitric provides support for serverless websockets. This feature allows you to connect client applications to your Nitric services using websocket gateways such as AWS APIGateway.
Projects with websockets will only be deployable to AWS at the moment. If you require support for additional clouds let us know: https://github.com/nitrictech/nitric/issues
Enabling Websocket support
Websocket support is currently in Preview. To enable it in your project add the following to your nitric.yaml
file
preview-features:
- websockets
Listening for events
There are three events that must be defined to deploy a valid websocket implementation. These are connect
, disconnect
and message
.
import { websocket } from '@nitric/sdk'
const socket = websocket('socket')
socket.on('connect', async (ctx) => {
// handle connections
})
socket.on('disconnect', async (ctx) => {
// handle disconnections
})
socket.on('message', async (ctx) => {
// handle messages
})
Managing connections
Nitric connects your services to a websocket interface, but it is up to you to manage the connections. Nitric provides kv
out of the box that can be used to do this or you can use any other store or database you like.
import { websocket, kv } from '@nitric/sdk'
// Initialize KV store for connections and a WebSocket
const kvStore = kv('connections').for('getting', 'setting', 'deleting')
const socket = websocket('example-websocket')
// Helper function to get current connections
async function getCurrentConnections() {
try {
const serializedList = await kvStore.get('connections')
return serializedList && serializedList['ids']
? JSON.parse(serializedList['ids'])
: []
} catch (error) {
console.error('Error getting current connections:', error)
return []
}
}
// Helper function to update connections list
async function updateConnections(connections) {
try {
const updatedSerializedList = JSON.stringify(connections)
await kvStore.set('connections', { ids: updatedSerializedList })
} catch (error) {
console.error('Error updating connections:', error)
}
}
// Handle new connections
socket.on('connect', async (ctx) => {
const connections = await getCurrentConnections()
connections.push(ctx.req.connectionId)
await updateConnections(connections)
})
// Handle disconnections
socket.on('disconnect', async (ctx) => {
const disconnectedId = ctx.req.connectionId
const connections = await getCurrentConnections()
const index = connections.indexOf(disconnectedId)
if (index > -1) {
connections.splice(index, 1)
await updateConnections(connections)
}
})
Sending Messages
import { websocket, kv } from '@nitric/sdk'
// Initialize KV store for connections and a WebSocket
const kvStore = kv('connections').for('getting', 'setting', 'deleting')
const socket = websocket('example-websocket')
// Helper function to get current connections
async function getCurrentConnections() {
try {
const serializedList = await kvStore.get('connections')
return serializedList && serializedList['ids']
? JSON.parse(serializedList['ids'])
: []
} catch (error) {
console.error('Error getting current connections:', error)
return []
}
}
// Helper function to update connections list
async function updateConnections(connections) {
try {
const updatedSerializedList = JSON.stringify(connections)
await kvStore.set('connections', { ids: updatedSerializedList })
} catch (error) {
console.error('Error updating connections:', error)
}
}
// Handle new connections
socket.on('connect', async (ctx) => {
const connections = await getCurrentConnections()
connections.push(ctx.req.connectionId)
await updateConnections(connections)
})
// Handle disconnections
socket.on('disconnect', async (ctx) => {
const disconnectedId = ctx.req.connectionId
const connections = await getCurrentConnections()
const index = connections.indexOf(disconnectedId)
if (index > -1) {
connections.splice(index, 1)
await updateConnections(connections)
}
})
// Send messages
socket.on('message', async (ctx) => {
const message = ctx.req.text()
const connections = await getCurrentConnections()
// Send the message to each connection
connections.forEach(async (connectionId) => {
try {
if (connectionId !== ctx.req.connectionId) {
await socket.send(connectionId, message)
}
} catch (error) {
console.error(`Error sending message to ${connectionId}:`, error)
}
})
})
Do not send messages to a connection during it's connect
callback, if you
need to acknowledge connection, do so by using a topic