HTTP and WebSockets on one listener

Documentation for Redweb 0.16.1. Install that exact version when following these examples.

Register an Express endpoint and a socket route with defineApp. One run call starts their shared listener; the application owns shutdown.

Use the complete http-ws recipe for setup, files, and tests.

tsx
import { BaseHandler, defineApp, METHODS, SocketRoute, type RedWebSocket } from 'redweb';

export class Hello extends BaseHandler {
    constructor() { super('hello'); }

    onMessage(socket: RedWebSocket) {
        socket.sendJson({ type: 'hello', message: 'Hello from the server!' });
    }
}

export class ChatRoute extends SocketRoute {
    constructor() {
        super({ path: '/chat', handlers: [Hello], allowDuplicateConnections: true });
    }
}

export const app = defineApp({
    sockets: [ChatRoute],
    port: Number(process.env.PORT ?? 8181),
    bind: '127.0.0.1',
    publicPaths: [],
    httpServices: [{ serviceName: '/health', method: METHODS.GET, function: (_req, res) => res.json({ ok: true }) }],
});

if (require.main === module) void app.run().catch(error => { console.error(error); process.exitCode = 1; });

Notes and boundaries

  • GET /health returns JSON; ws://127.0.0.1:8181/chat accepts {"type":"hello"}. The HTTP endpoint reports liveness, not readiness.
  • Use the complete http-ws starter for compiler configuration and actual HTTP/WebSocket tests. It binds loopback for local development.
  • Application shutdown closes both HTTP and socket resources. Configure authentication, trusted origins, limits and HTTPS/WSS before public deployment.