Utilitaire WebSocket
L’utilitaire WebSocket facilite l’utilisation de WebSockets côté serveur dans les applications Hono. Des adaptateurs sont actuellement disponibles pour Cloudflare Workers / Pages, Deno, Bun et Node.js.
Importation
L’adaptateur de chaque environnement d’exécution est fourni dans un paquet distinct (@hono/cloudflare-workers, @hono/deno, @hono/bun, ...). Installez celui qui correspond à votre environnement.
import { Hono } from 'hono'
import { upgradeWebSocket } from '@hono/cloudflare-workers'import { Hono } from 'hono'
import { upgradeWebSocket } from '@hono/deno'import { Hono } from 'hono'
import { upgradeWebSocket, websocket } from '@hono/bun'
// ...
export default {
fetch: app.fetch,
websocket,
}import { serve, upgradeWebSocket } from '@hono/node-server'
import { Hono } from 'hono'
import { WebSocketServer } from 'ws'Sur Node.js, la prise en charge des WebSockets est intégrée à @hono/node-server. Pour l’activer, installez ws et, si vous utilisez TypeScript, @types/ws. Créez ensuite un WebSocketServer avec { noServer: true } et passez-le à serve() via l’option websocket.
@hono/node-ws est obsolète.
upgradeWebSocket()
upgradeWebSocket() renvoie un gestionnaire chargé de traiter le WebSocket.
const app = new Hono()
app.get(
'/ws',
upgradeWebSocket((c) => {
return {
onMessage(event, ws) {
console.log(`Message from client: ${event.data}`)
ws.send('Hello from server!')
},
onClose: () => {
console.log('Connection closed')
},
}
})
)Événements disponibles :
onOpen- Cloudflare Workers ne le prend actuellement pas en charge.onMessageonCloseonError
Attention
Si vous utilisez un middleware qui modifie les en-têtes, par exemple pour appliquer CORS, sur une route utilisant l’utilitaire WebSocket, une erreur peut indiquer qu’il est impossible de modifier des en-têtes immuables. Cela se produit parce que upgradeWebSocket() modifie aussi les en-têtes en interne.
Soyez donc vigilant lorsque vous utilisez simultanément l’utilitaire WebSocket et des middlewares.
Mode RPC
Les gestionnaires définis avec l’utilitaire WebSocket prennent en charge le mode RPC.
// server.ts
const wsApp = app.get(
'/ws',
upgradeWebSocket((c) => {
//...
})
)
export type WebSocketApp = typeof wsApp
// client.ts
const client = hc<WebSocketApp>('http://localhost:8787')
const socket = client.ws.$ws() // A WebSocket object for a clientExemples
Consultez les exemples utilisant l’utilitaire WebSocket.
Serveur et client
// server.ts
import { Hono } from 'hono'
import { upgradeWebSocket } from '@hono/cloudflare-workers'
const app = new Hono().get(
'/ws',
upgradeWebSocket(() => {
return {
onMessage: (event) => {
console.log(event.data)
},
}
})
)
export default app// client.ts
import { hc } from 'hono/client'
import type app from './server'
const client = hc<typeof app>('http://localhost:8787')
const ws = client.ws.$ws(0)
ws.addEventListener('open', () => {
setInterval(() => {
ws.send(new Date().toString())
}, 1000)
})Bun avec JSX
import { Hono } from 'hono'
import { upgradeWebSocket, websocket } from '@hono/bun'
import { html } from 'hono/html'
const app = new Hono()
app.get('/', (c) => {
return c.html(
<html>
<head>
<meta charset='UTF-8' />
</head>
<body>
<div id='now-time'></div>
{html`
<script>
const ws = new WebSocket('ws://localhost:3000/ws')
const $nowTime = document.getElementById('now-time')
ws.onmessage = (event) => {
$nowTime.textContent = event.data
}
</script>
`}
</body>
</html>
)
})
const ws = app.get(
'/ws',
upgradeWebSocket((c) => {
let intervalId
return {
onOpen(_event, ws) {
intervalId = setInterval(() => {
ws.send(new Date().toString())
}, 200)
},
onClose() {
clearInterval(intervalId)
},
}
})
)
export default {
fetch: app.fetch,
websocket,
}Node.js
import { serve, upgradeWebSocket } from '@hono/node-server'
import { Hono } from 'hono'
import { WebSocketServer } from 'ws'
const app = new Hono()
app.get(
'/ws',
upgradeWebSocket(() => ({
onMessage(event, ws) {
ws.send(event.data)
},
}))
)
const wss = new WebSocketServer({ noServer: true })
serve({
fetch: app.fetch,
websocket: { server: wss },
})