I'm building a WebSocket server using TypeScript, Node.js, and Fastify. When I connect to it with a client, I can establish a connection, but the server doesn't respond to any messages I send.
Setup
Server code (index.mts):
"use strict";
import fastify from "fastify";
import fastifyWebsocket from "@fastify/websocket";
import { FastifyRequest } from "fastify";
const fastifyServer = fastify();
fastifyServer.register(fastifyWebsocket);
fastifyServer.get(
"/",
{ websocket: true },
(connection: any, request: FastifyRequest) => {
const { socket } = connection;
socket.on("message", async (message: string) => {
console.log("Received message:", message);
socket.send("Hello from server");
});
socket.on("close", () => {
console.log("WebSocket connection closed");
});
}
);
fastifyServer.listen({ host: "0.0.0.0", port: 3000 }, (err: Error | null) => {
console.log("Server started on port 3000");
if (err) {
fastifyServer.log.error(err);
process.exit(1);
}
});
package.json:
{
"name": "fastifywebsocket",
"version": "1.0.0",
"description": "",
"main": "index.mjs",
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node dist/index.mjs",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Toshiyuki Ogura",
"license": "ISC",
"type": "module",
"dependencies": {
"@fastify/websocket": "^11.0.2",
"fastify": "^5.2.2"
},
"devDependencies": {
"@types/node": "^22.14.0",
"typescript": "^5.8.3"
}
}
tsconfig.json:
{
"compilerOptions": {
"target": "es2016",
"module": "ES6",
"rootDir": "./src",
"moduleResolution": "node",
"typeRoots": ["./node_modules/@types"],
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Issue
I build and run the server with:
npm run build
npm start
Then I connect from a client using websocat:
websocat ws://localhost:3000/
The connection seems to be established, but when I send a message from the client (like "abc" + Enter), the server doesn't show any logs and doesn't respond. The server should:
But nothing happens. I don't see any errors either.
What I've tried
What could be causing this lack of response? Is there something wrong with my WebSocket configuration?
When using @fastify/websocket
, plugin needs to be registered before all routes.
It basically means, in your case, to wait for plugin registration to complete before defining websocket routes. See the code example below based on the code in your question (note changes in lines 5 and 10)
import fastify, { type FastifyRequest } from "fastify";
import fastifyWebsocket, { type WebSocket } from "@fastify/websocket";
const fastifyServer = fastify();
// waiting for plugin registration to complete
await fastifyServer.register(fastifyWebsocket);
// route gets a WebSocket object and not connection: any
fastifyServer.get(
"/",
{ websocket: true },
(socket: WebSocket, _request: FastifyRequest) => {
socket.on("message", async (message: string) => {
console.log("Received message:", message);
socket.send("Hello from server");
});
socket.on("close", () => {
console.log("WebSocket connection closed");
});
},
);
fastifyServer.listen({ host: "0.0.0.0", port: 3000 }, (err: Error | null) => {
console.log("Server started on port 3000");
if (err) {
fastifyServer.log.error(err);
process.exit(1);
}
});