WebSocket support for Fastify. Built upon ws.
npm install fastify-websocket --save
>=nodejs-8.0.0
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.