Websocket Express
title: "WebSocket with Express.js" description: "Learn how to integrate WebSocket with Express.js applications for combining REST APIs with real-time WebSocket communication." weight: 15 date: 2026-06-28 lastmod: 2026-06-28 tags: ["apis", "websocket"]
Express.js can serve both HTTP REST endpoints and WebSocket connections on the same server. This lesson covers integrating the `ws` library with Express for hybrid HTTP/WebSocket applications.
## What You'll Learn
- Setting up WebSocket with Express
- Sharing Express middleware with WebSocket
- HTTP-to-WebSocket upgrade routing
- Hybrid REST + WebSocket architecture
- Authentication integration
## Why It Matters
Most web applications need both REST APIs and real-time features. Running both on the same server simplifies deployment, shares authentication logic, and reduces operational complexity.
## Real-World Use
A project management app uses Express for REST endpoints (CRUD for projects, tasks) and WebSocket for real-time collaboration (live cursor updates, drag-and-drop sync, notification delivery).
## Flow Chart
```mermaid
flowchart LR
A[Client] --> B[Express Server]
B --> C{Route}
C -->|/api/*| D[REST Handler]
C -->|/ws| E[WebSocket Upgrade]
D --> F[JSON Response]
E --> G[WebSocket Connection]
G <--> H[Real-time Messages]
Code Examples
Example 1: Express with WebSocket Server
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// Express routes
app.get('/api/status', (req, res) => {
res.json({ status: 'running', clients: wss.clients.size });
});
// WebSocket connections
wss.on('connection', (ws, req) => {
console.log('WebSocket client connected');
ws.on('message', (message) => {
const data = JSON.parse(message);
// Broadcast to all clients
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(data));
}
});
});
ws.send(JSON.stringify({ type: 'connected', message: 'Welcome' }));
});
server.listen(3000, () => {
console.log('Server on http://localhost:3000');
console.log('WebSocket on ws://localhost:3000/ws');
});
Expected output: Express serves REST on port 3000, and WebSocket accepts connections on the same port.
Example 2: Route-Based WebSocket Upgrade
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
// Separate WebSocket servers for different paths
const chatWss = new WebSocket.Server({ noServer: true });
const notificationWss = new WebSocket.Server({ noServer: true });
chatWss.on('connection', (ws) => {
ws.on('message', (msg) => console.log('Chat:', msg.toString()));
ws.send('Connected to chat');
});
notificationWss.on('connection', (ws) => {
ws.send('Connected to notifications');
});
server.on('upgrade', (request, socket, head) => {
const pathname = new URL(request.url, 'http://localhost').pathname;
if (pathname === '/ws/chat') {
chatWss.handleUpgrade(request, socket, head, (ws) => {
chatWss.emit('connection', ws, request);
});
} else if (pathname === '/ws/notifications') {
notificationWss.handleUpgrade(request, socket, head, (ws) => {
notificationWss.emit('connection', ws, request);
});
} else {
socket.destroy();
}
});
app.get('/api/info', (req, res) => {
res.json({
chatConnected: chatWss.clients.size,
notificationConnected: notificationWss.clients.size,
});
});
server.listen(3000);
Expected output: Different WebSocket endpoints for chat and notifications, routed by URL path.
Example 3: Express Middleware with WebSocket Auth
const express = require('express');
const WebSocket = require('ws');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(express.json());
// Express authentication middleware
app.use('/api', (req, res, next) => {
const token = req.cookies.token || req.headers.authorization;
if (!token) return res.status(401).json({ error: 'Unauthorized' });
req.user = verifyToken(token);
next();
});
const server = http.createServer(app);
const wss = new WebSocket.Server({ noServer: true });
wss.on('connection', (ws, req) => {
console.log(`User ${req.user.id} connected via WebSocket`);
ws.send(JSON.stringify({ type: 'auth', status: 'connected' }));
});
server.on('upgrade', (request, socket, head) => {
const token = parseCookies(request.headers.cookie).token
|| request.headers.authorization;
if (!token) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
const user = verifyToken(token);
if (!user) {
socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
socket.destroy();
return;
}
request.user = user;
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request);
});
});
Expected output: WebSocket connections require valid authentication tokens, with unauthorized connections rejected during upgrade.
Common Mistakes
| Mistake | Explanation |
|---|---|
| Not sharing the HTTP server | Both Express and WebSocket must share the same http.createServer instance |
| Missing upgrade handler | Without the upgrade event handler, WebSocket connections fail on custom paths |
| Blocking the event loop with WebSocket handlers | WebSocket message handlers should be async and non-blocking |
| Forgetting to handle server errors | Add error handlers for both Express and WebSocket server errors |
| Mixing ws and wss on same port | A port cannot serve both HTTP and HTTPS; choose one scheme for the server |
Practice Questions
- How do you run WebSocket and Express on the same port?
- How do you route WebSocket connections to different handlers based on URL?
- How do you share authentication between Express and WebSocket?
- What is the
noServeroption in WebSocket.Server? - How do you broadcast messages to all connected WebSocket clients?
Challenge
Build a hybrid application with Express REST endpoints for user management and WebSocket for real-time notifications. Users authenticate via REST, receive a JWT token, and use that token to authenticate their WebSocket connection.
FAQ
Mini Project
Build a collaborative task management app with Express REST API and WebSocket real-time updates. Users can create, update, and delete tasks via REST, and all changes are broadcast to connected clients via WebSocket. Include authentication for both HTTP and WebSocket.
What's Next
Learn about Socket.IO for enhanced WebSocket functionality
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro