Full declaration syntax is not typed correctly for `websocket: true`
Prerequisites
- [X] I have written a descriptive issue title
- [X] I have searched existing issues to ensure the bug has not already been reported
Fastify version
5.2.0
Plugin version
11.0.1
Node.js version
22.12
Operating system
macOS
Operating system version (i.e. 20.04, 11.3, 10)
Sonoma 14.5
Description
It seems that the full declaration syntax is not supported by @fastify/websocket types.
Also, when the wsHandler property is set, the behaviour is the following:
- the
handlerproperty is still required and typescript throws error when it is not in place; - when the
handlerproperty is also set, the ws connection is handled by thehandlerproperty whilewsHandleris ignored.
Is this the expected behaviour?
import Fastify from 'fastify';
import FastifyWebsocket from '@fastify/websocket';
const app = Fastify();
app.register(FastifyWebsocket);
app.route({
method: 'GET',
url: '/',
websocket: true,
handler: async (websocket, request) => {
// 'websocket' is typed as FastifyRequest, not WebSocket
// 'request' is typed as FastifyReply, not FastifyRequest
},
});
app.route({
method: 'GET',
url: '/',
websocket: true,
wsHandler: (socket, request) => {
console.log('WS'); // not printed
},
handler: (socket, request) => {
console.log(socket.constructor.name === 'WebSocket'); // prints true (when executing "new WebSocket('ws://localhost:3000/')" in the browser)
},
});
Somewhat related issue: https://github.com/fastify/fastify-websocket/issues/133
Expected Behavior
- The full declaration syntax (
RouteOptionstype) is typed correctly. - wsHandler is executed for ws connection when both
handlerandwsHandlerare defined.
the handler property is still required and typescript throws error when it is not in place;
Not tested yet.
when the handler property is also set, the ws connection is handled by the handler property while wsHandler is ignored.
From your example, it is expected behavior because websocket: true option means to use handler as the websocket handler.
You should remove the websocket property in the route option.
I am facing this issue too. Even when I make a WebSocket request, the wsHandler is never reached.
{
method: 'GET',
url: '/ws/logs',
wsHandler: (socket, request) => {
console.log('WS'); // This is never printed
},
handler: (socket, request) => {
console.log(socket.constructor.name);
// Prints "_Request" when executing "new WebSocket('ws://localhost:3000/ws/logs')" in the browser
},
}
My route is defined using the full declaration syntax.
Anything I’m missing?
Nah, same here. Something is wrong, it always hits handler:
Ok, this is probably caused by a separate issue. You can do this and it will work:
import Fastify from 'fastify';
import FastifyWebsocket from '@fastify/websocket';
const app = Fastify();
app.register(FastifyWebsocket);
app.register(async function (app) {
app.route({
method: 'GET',
url: '/',
wsHandler: (socket, request) => {
console.log('WS'); // not printed
},
handler: (socket, request) => {
console.log(socket.constructor.name === 'WebSocket'); // prints true (when executing "new WebSocket('ws://localhost:3000/')" in the browser)
},
});
})
I am facing this issue too. Even when I make a WebSocket request, the
wsHandleris never reached.{ method: 'GET', url: '/ws/logs', wsHandler: (socket, request) => { console.log('WS'); // This is never printed }, handler: (socket, request) => { console.log(socket.constructor.name); // Prints "_Request" when executing "new WebSocket('ws://localhost:3000/ws/logs')" in the browser }, } My route is defined using the full declaration syntax.
Anything I’m missing?
I don't know why, but if you enter websocket:false in the ‘route’ object or don't send it at all, the wsHandler function works. If you set it to true, the handler function works.
@fastify/websocket version: 10.0.1 fastify version: 4.28.1
I had this problem and I just figured it out, the clue was in the documentation:
When using @fastify/websocket, it needs to be registered before all routes in order to be able to intercept websocket connections to existing routes and close the connection on non-websocket routes.
Need to do it likem this
import websocket from '@fastify/websocket'
const server = fastify();
//register websocket server
server.register(websocket);
// then register routes
server.register(routes)
dotenv.config(); // load dotenv
then it will work correctly:
you need to install ws types
pnpm add -D @types/ws
npm i @types/ws -D