WebSocket support for Fastify. Built upon ws.
npm install fastify-websocket --save
There are two possible ways of using this plugin: with a global handler or with a per route handler.
All you need to do is to add it to your project with register
and pass handle function. You are done!
'use strict'
const fastify = require('fastify')()
fastify.register(require('fastify-websocket'), {
handle,
options: {
maxPayload: 1048576, // we set the maximum allowed messages size to 1 MiB (1024 bytes * 1024 bytes)
path: '/fastify', // we accept only connections matching this path e.g.: ws://localhost:3000/fastify
verifyClient: function (info, next) {
if (info.req.headers['x-fastify-header'] !== 'fastify is awesome !') {
return next(false) // the connection is not allowed
}
next(true) // the connection is allowed
}
}
})
function handle (conn) {
conn.pipe(conn) // creates an echo server
}
fastify.listen(3000, err => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
After registering this plugin, you can choose on which routes the WS server will respond. This could be achieved by adding websocket: true
property to routeOptions
on a fastify's .get
route. In this case two arguments will be passed to the handler: socket connection and the original http.IncomingMessage
(instead of the usual fastify's request and reply objects).
'use strict'
const fastify = Fastify()
fastify.register(require('fastify-websocket'))
fastify.get('/', { websocket: true }, (connection, req) => {
connection.socket.on('message', message => {
// message === 'hi from client'
connection.socket.send('hi from server')
})
})
fastify.listen(3000, err => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
In this case there won't be any global handler, so it will respond with a 404 error on every unregistered route, closing the incoming upgrade connection requests.
The route handler receives route params as a third argument:
fastify.get('/ws/:id', { websocket: true }, (connection, req, params) => {
connection.write(`hi on stream ${params.id}`)
})
However you can still pass a default global handler, that will be used as default handler.
'use strict'
const fastify = require('fastify')()
function handle (conn) {
conn.pipe(conn) // creates an echo server
}
fastify.register(require('fastify-websocket'), {
handle,
options: { maxPayload: 1048576 }
})
fastify.get('/', { websocket: true }, (connection, req) => {
connection.socket.on('message', message => {
// message === 'hi from client'
connection.socket.send('hi from server')
})
})
fastify.listen(3000, err => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
If you need to handle both HTTP requests and incoming socket connections on the same route, you can still do it using the full declaration syntax, adding a wsHandler
property.
'use strict'
const fastify = require('fastify')()
function handle (conn) {
conn.pipe(conn) // creates an echo server
}
fastify.register(require('fastify-websocket'), {
handle,
options: { maxPayload: 1048576 }
})
fastify.route({
method: 'GET',
url: '/hello',
handler: (req, reply) => {
// this will handle http requests
reply.send({ hello: 'world' })
},
wsHandler: (conn, req) => {
// this will handle websockets connections
conn.setEncoding('utf8')
conn.write('hello client')
conn.once('data', chunk => {
conn.end()
})
}
})
fastify.listen(3000, err => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
fastify-websocket
accept the same options as ws
:
objectMode
- Send each chunk on its own, and do not try to pack them in a single websocket frame.host
- The hostname where to bind the server.port
- The port where to bind the server.backlog
- The maximum length of the queue of pending connections.server
- A pre-created Node.js HTTP/S server.verifyClient
- A function which can be used to validate incoming connections.handleProtocols
- A function which can be used to handle the WebSocket subprotocols.path
- Accept only connections matching this path.noServer
- Enable no server mode.clientTracking
- Specifies whether or not to track clients.perMessageDeflate
- Enable/disable permessage-deflate.maxPayload
- The maximum allowed message size in bytes.
For more informations you can check ws
options documentation.
NB: By default if you do not provide a server
option fastify-websocket
will bind your websocket server instance to the scoped fastify
instance.
This project is kindly sponsored by nearForm.
Licensed under MIT.