Passerelles WebSocket avec l’adaptateur Socket.IO
Implémentez des gestionnaires @WebSocketGateway, des salles et des hooks de cycle de vie pour les communications en direct.
Passerelles WebSocket avec l’adaptateur Socket.IO est une leçon NestJS Enterprise Backend APIs gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage NestJS Enterprise Backend APIs, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours NestJS Enterprise Backend APIs comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
Why Gateways Exist
REST handles request/response, but real-time features (chat, presence, live dashboards) need a persistent, bidirectional channel. NestJS wraps this with a WebSocket Gateway.
- A gateway is a provider decorated with
@WebSocketGateway(). - By default Nest uses the Socket.IO platform adapter (
@nestjs/platform-socket.io). - Gateways are normal Nest classes: they support dependency injection, guards, pipes, and interceptors just like controllers.
Install the deps with npm i @nestjs/websockets @nestjs/platform-socket.io socket.io.
Declaring a Gateway
Decorate a class with @WebSocketGateway() and register it as a provider in a module. You can pass a port and options such as namespace and CORS config.
@SubscribeMessage('event')binds a handler to an inbound Socket.IO event.- The return value (or a
WsResponse) is emitted back to the calling client.
Below, clients sending ping receive a pong reply.
import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
@WebSocketGateway({ namespace: '/chat', cors: { origin: '*' } })
export class ChatGateway {
@SubscribeMessage('ping')
handlePing(@MessageBody() data: string): { event: string; data: string } {
return { event: 'pong', data: `received: ${data}` };
}
}Accessing the Server Instance
To broadcast to many clients you need the underlying Socket.IO Server. Inject it with the @WebSocketServer() property decorator.
server.emit('event', payload)sends to every connected client in the namespace.- This is the foundation for fan-out features like global announcements.
import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody } from '@nestjs/websockets';
import { Server } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@WebSocketServer()
server: Server;
@SubscribeMessage('broadcast')
handleBroadcast(@MessageBody() message: string): void {
this.server.emit('announcement', message);
}
}The Connected Socket
Each client has its own Socket. Inject it per-handler with @ConnectedSocket() to read auth data, the socket id, or to reply only to that client.
client.emit(...)targets just the sender.client.iduniquely identifies the connection.client.handshakeexposes headers, query, and auth handed in at connect time.
import { WebSocketGateway, SubscribeMessage, MessageBody, ConnectedSocket } from '@nestjs/websockets';
import { Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@SubscribeMessage('whoami')
whoAmI(@ConnectedSocket() client: Socket, @MessageBody() _: unknown): void {
client.emit('identity', { id: client.id, token: client.handshake.auth?.token });
}
}Lifecycle Hooks
Gateways can implement lifecycle interfaces to react to connection events:
OnGatewayInit→afterInit(server)runs once the server is ready.OnGatewayConnection→handleConnection(client)fires per new client.OnGatewayDisconnect→handleDisconnect(client)fires when a client leaves.
Use these for presence tracking, auth on connect, and cleanup.
import { WebSocketGateway, OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
private readonly logger = new Logger(ChatGateway.name);
afterInit(server: Server): void {
this.logger.log('Gateway initialized');
}
handleConnection(client: Socket): void {
this.logger.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket): void {
this.logger.log(`Client disconnected: ${client.id}`);
}
}Rooms: Grouping Sockets
A room is a server-side label you attach to sockets so you can broadcast to a subset. A socket can belong to many rooms.
client.join('room')adds the socket to a room.client.leave('room')removes it.- Socket.IO automatically puts each socket in a room named after its own
client.id.
Rooms are how you build per-channel chat, per-tenant dashboards, or per-document collaboration.
import { WebSocketGateway, SubscribeMessage, MessageBody, ConnectedSocket } from '@nestjs/websockets';
import { Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@SubscribeMessage('joinRoom')
joinRoom(@ConnectedSocket() client: Socket, @MessageBody() room: string): void {
client.join(room);
client.emit('joined', room);
}
}Broadcasting to a Room
Target a room with server.to('room').emit(...). To exclude the sender, emit from the client socket: client.to('room').emit(...) sends to everyone in the room except that client.
server.to(room).emit(...)→ everyone in the room.client.to(room).emit(...)→ everyone in the room but the sender.
import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody, ConnectedSocket } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@WebSocketServer() server: Server;
@SubscribeMessage('sendToRoom')
sendToRoom(
@ConnectedSocket() client: Socket,
@MessageBody() body: { room: string; text: string },
): void {
client.to(body.room).emit('message', { from: client.id, text: body.text });
}
}Acknowledgements with WsResponse
Socket.IO supports request/response style acknowledgements. In Nest you can return a value, a WsResponse<T> object, or even an Observable that streams multiple emissions back.
- Return
{ event, data }to emit a named event back to the caller. - Returning an
Observableemits one message per value, useful for progress updates.
import { WebSocketGateway, SubscribeMessage, MessageBody, WsResponse } from '@nestjs/websockets';
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@WebSocketGateway({ namespace: '/jobs' })
export class JobsGateway {
@SubscribeMessage('countdown')
countdown(@MessageBody() n: number): Observable<WsResponse<number>> {
const ticks = Array.from({ length: n }, (_, i) => n - i);
return from(ticks).pipe(map((value) => ({ event: 'tick', data: value })));
}
}Validation with Pipes
Gateways reuse Nest's ValidationPipe, but errors are thrown as WsException rather than HTTP exceptions. Apply the pipe at the handler or gateway level and validate a DTO via @MessageBody().
- Set
transform: trueso plain payloads become class instances. - A
WsExceptionis serialized to anexceptionevent on the client.
import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
import { UsePipes, ValidationPipe } from '@nestjs/common';
import { IsString, MinLength } from 'class-validator';
class SendMessageDto {
@IsString() @MinLength(1)
text: string;
}
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway {
@UsePipes(new ValidationPipe({ transform: true }))
@SubscribeMessage('send')
send(@MessageBody() dto: SendMessageDto): { event: string; data: string } {
return { event: 'sent', data: dto.text };
}
}Authenticating on Connect
Authenticate clients during handleConnection by reading the token from the handshake and disconnecting unauthorized sockets early. Storing the user on client.data makes it available to every later handler.
- Token usually arrives via
handshake.auth.tokenor anAuthorizationheader. - Call
client.disconnect()to reject bad clients before they join rooms.
import { WebSocketGateway, OnGatewayConnection } from '@nestjs/websockets';
import { Socket } from 'socket.io';
import { JwtService } from '@nestjs/jwt';
@WebSocketGateway({ namespace: '/chat' })
export class ChatGateway implements OnGatewayConnection {
constructor(private readonly jwt: JwtService) {}
async handleConnection(client: Socket): Promise<void> {
try {
const token = client.handshake.auth?.token as string;
client.data.user = await this.jwt.verifyAsync(token);
} catch {
client.emit('error', 'Unauthorized');
client.disconnect();
}
}
}Swapping the Adapter for Scale
Out of the box, Socket.IO state lives in a single process. To run multiple Nest instances behind a load balancer you must share room/emit state. Use a custom adapter with the Redis adapter so broadcasts reach clients on other nodes.
- Subclass
IoAdapterand attach@socket.io/redis-adapterincreateIOServer. - Register it via
app.useWebSocketAdapter(new RedisIoAdapter(app))inmain.ts.
import { IoAdapter } from '@nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
export class RedisIoAdapter extends IoAdapter {
private adapterConstructor: ReturnType<typeof createAdapter>;
async connectToRedis(): Promise<void> {
const pub = createClient({ url: 'redis://localhost:6379' });
const sub = pub.duplicate();
await Promise.all([pub.connect(), sub.connect()]);
this.adapterConstructor = createAdapter(pub, sub);
}
createIOServer(port: number, options?: ServerOptions): any {
const server = super.createIOServer(port, options);
server.adapter(this.adapterConstructor);
return server;
}
}Quick Check
Test your understanding of room broadcasting semantics.
Recap
You built a real-time layer with NestJS WebSocket gateways on the Socket.IO adapter:
- Gateway basics:
@WebSocketGateway()providers with@SubscribeMessagehandlers; inject the server via@WebSocketServer()and the per-client socket via@ConnectedSocket(). - Lifecycle hooks:
afterInit,handleConnection, andhandleDisconnectfor init, presence, and cleanup. - Rooms:
client.join/leave, thenserver.to(room)for everyone orclient.to(room)to exclude the sender. - Robustness: validate payloads with
ValidationPipe(errors becomeWsException), authenticate inhandleConnection, and use acknowledgements/Observables for replies. - Scale: swap in a Redis-backed
IoAdapterso broadcasts work across multiple instances.
Questions Fréquemment Posées
La leçon « Passerelles WebSocket avec l’adaptateur Socket.IO » est-elle gratuite ?
Oui — le texte complet de « Passerelles WebSocket avec l’adaptateur Socket.IO » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours NestJS Enterprise Backend APIs, passe à CoddyKit PRO. Le cours NestJS Enterprise Backend APIs comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Passerelles WebSocket avec l’adaptateur Socket.IO » ?
Implémentez des gestionnaires @WebSocketGateway, des salles et des hooks de cycle de vie pour les communications en direct. Tu pratiques NestJS Enterprise Backend APIs avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer NestJS Enterprise Backend APIs ?
Aucune expérience préalable n'est requise. NestJS Enterprise Backend APIs sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « Passerelles WebSocket avec l’adaptateur Socket.IO » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon NestJS Enterprise Backend APIs ?
Oui. Chaque leçon NestJS Enterprise Backend APIs inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Passerelles WebSocket avec l’adaptateur Socket.IO
- Authentifier et protéger les connexions Socket
- Événements envoyés par le serveur pour une diffusion unidirectionnelle
- Mettre à l’échelle le temps réel avec un adaptateur Redis Pub/Sub