4.0 KiB
4.0 KiB
WebSocket
Basic WebSocket
import { Elysia } from 'elysia'
new Elysia()
.ws('/chat', {
message(ws, message) {
ws.send(message) // Echo back
}
})
.listen(3000)
With Validation
import { Elysia, t } from 'elysia'
.ws('/chat', {
body: t.Object({
message: t.String(),
username: t.String()
}),
response: t.Object({
message: t.String(),
timestamp: t.Number()
}),
message(ws, body) {
ws.send({
message: body.message,
timestamp: Date.now()
})
}
})
Lifecycle Events
.ws('/chat', {
open(ws) {
console.log('Client connected')
},
message(ws, message) {
console.log('Received:', message)
ws.send('Echo: ' + message)
},
close(ws) {
console.log('Client disconnected')
},
error(ws, error) {
console.error('Error:', error)
}
})
Broadcasting
const connections = new Set<any>()
.ws('/chat', {
open(ws) {
connections.add(ws)
},
message(ws, message) {
// Broadcast to all connected clients
for (const client of connections) {
client.send(message)
}
},
close(ws) {
connections.delete(ws)
}
})
With Authentication
.ws('/chat', {
beforeHandle({ headers, status }) {
const token = headers.authorization?.replace('Bearer ', '')
if (!verifyToken(token)) {
return status(401)
}
},
message(ws, message) {
ws.send(message)
}
})
Room-Based Chat
const rooms = new Map<string, Set<any>>()
.ws('/chat/:room', {
open(ws) {
const room = ws.data.params.room
if (!rooms.has(room)) {
rooms.set(room, new Set())
}
rooms.get(room)!.add(ws)
},
message(ws, message) {
const room = ws.data.params.room
const clients = rooms.get(room)
if (clients) {
for (const client of clients) {
client.send(message)
}
}
},
close(ws) {
const room = ws.data.params.room
const clients = rooms.get(room)
if (clients) {
clients.delete(ws)
if (clients.size === 0) {
rooms.delete(room)
}
}
}
})
With State/Context
.ws('/chat', {
open(ws) {
ws.data.userId = generateUserId()
ws.data.joinedAt = Date.now()
},
message(ws, message) {
const response = {
userId: ws.data.userId,
message,
timestamp: Date.now()
}
ws.send(response)
}
})
Client Usage (Browser)
const ws = new WebSocket('ws://localhost:3000/chat')
ws.onopen = () => {
console.log('Connected')
ws.send('Hello Server!')
}
ws.onmessage = (event) => {
console.log('Received:', event.data)
}
ws.onerror = (error) => {
console.error('Error:', error)
}
ws.onclose = () => {
console.log('Disconnected')
}
Eden Treaty WebSocket
// Server
export const app = new Elysia()
.ws('/chat', {
message(ws, message) {
ws.send(message)
}
})
export type App = typeof app
// Client
import { treaty } from '@elysiajs/eden'
import type { App } from './server'
const api = treaty<App>('localhost:3000')
const chat = api.chat.subscribe()
chat.subscribe((message) => {
console.log('Received:', message)
})
chat.send('Hello!')
Headers in WebSocket
.ws('/chat', {
header: t.Object({
authorization: t.String()
}),
beforeHandle({ headers, status }) {
const token = headers.authorization?.replace('Bearer ', '')
if (!token) return status(401)
},
message(ws, message) {
ws.send(message)
}
})
Query Parameters
.ws('/chat', {
query: t.Object({
username: t.String()
}),
message(ws, message) {
const username = ws.data.query.username
ws.send(`${username}: ${message}`)
}
})
// Client
const ws = new WebSocket('ws://localhost:3000/chat?username=john')
Compression
new Elysia({
websocket: {
perMessageDeflate: true
}
})
.ws('/chat', {
message(ws, message) {
ws.send(message)
}
})