Як реалізувати WebSocket Gateways у NestJS?
WebSocket Gateways у NestJS
NestJS надає першокласну підтримку для WebSocket комунікації через Gateways. Gateways — це класи, анотовані @WebSocketGateway(), які обробляють двосторонню комунікацію в реальному часі.
Налаштування
bash
npm install @nestjs/websockets @nestjs/platform-socket.io socket.ioОсновний Gateway
typescript
import {
WebSocketGateway,
WebSocketServer,
SubscribeMessage,
MessageBody,
ConnectedSocket,
OnGatewayConnection,
OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({
cors: { origin: '*' },
namespace: '/chat',
})
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;
handleConnection(client: Socket) {
console.log('Клієнт підключився:', client.id);
}
handleDisconnect(client: Socket) {
console.log('Клієнт відключився:', client.id);
}
@SubscribeMessage('message')
handleMessage(
@MessageBody() data: { room: string; text: string },
@ConnectedSocket() client: Socket,
) {
// Транслювати в кімнату
this.server.to(data.room).emit('message', {
user: client.id,
text: data.text,
timestamp: new Date(),
});
}
@SubscribeMessage('joinRoom')
handleJoinRoom(
@MessageBody() room: string,
@ConnectedSocket() client: Socket,
) {
client.join(room);
this.server.to(room).emit('userJoined', { userId: client.id });
return { event: 'joinedRoom', data: room };
}
}Реєстрація в Модулі
typescript
@Module({
providers: [ChatGateway, ChatService],
})
export class ChatModule {}Gateway з Аутентифікацією
typescript
@WebSocketGateway()
export class ChatGateway implements OnGatewayConnection {
constructor(private readonly authService: AuthService) {}
async handleConnection(client: Socket) {
try {
const token = client.handshake.auth.token;
const user = await this.authService.verifyToken(token);
client.data.user = user;
console.log(`Користувач ${user.name} підключився`);
} catch (err) {
client.emit('error', { message: 'Аутентифікація не вдалася' });
client.disconnect();
}
}
@SubscribeMessage('message')
handleMessage(
@MessageBody() data: { text: string },
@ConnectedSocket() client: Socket,
) {
const user = client.data.user;
this.server.emit('message', {
user: user.name,
text: data.text,
});
}
}Використання Guards з WebSockets
typescript
@Injectable()
export class WsAuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const client = context.switchToWs().getClient<Socket>();
const user = client.data.user;
return !!user;
}
}
@WebSocketGateway()
export class ChatGateway {
@UseGuards(WsAuthGuard)
@SubscribeMessage('message')
handleMessage(@MessageBody() data: any) {
// Тільки аутентифіковані користувачі можуть сюди потрапити
}
}Випромінювання з Сервісів
typescript
@Injectable()
export class NotificationService {
constructor(
@Inject('CHAT_GATEWAY')
private readonly chatGateway: ChatGateway,
) {}
async notifyUser(userId: string, notification: any) {
this.chatGateway.server
.to(`user:${userId}`)
.emit('notification', notification);
}
}Хуки Життєвого Циклу
| Хук | Коли |
|---|---|
OnGatewayInit | Після ініціалізації gateway |
OnGatewayConnection | Коли клієнт підключається |
OnGatewayDisconnect | Коли клієнт відключається |
Приклад Клієнта
typescript
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000/chat', {
auth: { token: 'jwt-token-here' },
});
socket.emit('joinRoom', 'general');
socket.emit('message', { room: 'general', text: 'Привіт!' });
socket.on('message', (data) => {
console.log(`${data.user}: ${data.text}`);
});Порада: Використовуйте Gateways NestJS для структурованої обробки WebSocket з впровадженням залежностей, Guards, Interceptors та Pipes — всі ті ж шаблони, які ви використовуєте в REST контролерах.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.