WebSocket en TypeScript : développement avancé d'applications temps réel

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

WebSocket en TypeScript : Construire des applications temps réel avancées

\n\n

Les applications temps réel sont devenues une partie essentielle du web moderne. Des chats et notifications aux jeux en ligne et plateformes de trading, la technologie WebSocket assure une connexion bidirectionnelle permanente entre le client et le serveur. À un niveau avancé, le développement de tels systèmes nécessite non seulement une compréhension du protocole, mais aussi la capacité de construire des architectures tolérantes aux pannes et évolutives. Dans cet article, nous verrons comment créer des applications WebSocket de qualité production en TypeScript, en utilisant les meilleures pratiques et modèles.

\n\n

1. Architecture et clustering du serveur WebSocket

\n\n

Un seul serveur WebSocket ne supportera pas la charge d'un projet réel. La tâche clé est d'organiser le clustering et l'échange de messages entre les instances. Considérons une architecture utilisant la bibliothèque ws et un bus d'événements Redis.

\n\n

Installons les dépendances :

\n
npm install ws redis ioredis @types/ws @types/ioredis
\n\n

Créons un serveur clusterisé de base :

\n\n
import { WebSocketServer, WebSocket } from 'ws';\nimport Redis from 'ioredis';\n\nconst redisPub = new Redis();\nconst redisSub = new Redis();\n\nconst wss = new WebSocketServer({ port: 8080 });\n\n// Canal pour la communication inter-serveurs\nconst CHANNEL = 'ws:messages';\n\nredisSub.subscribe(CHANNEL, (err, count) => {\n  if (err) console.error('Erreur d\'abonnement :', err);\n  console.log(`Abonné à ${count} canaux`);\n});\n\n// Réception des messages depuis d'autres instances\nredisSub.on('message', (channel, message) => {\n  const parsed = JSON.parse(message);\n  wss.clients.forEach((client) => {\n    if (client.readyState === WebSocket.OPEN) {\n      client.send(parsed.data);\n    }\n  });\n});\n\nwss.on('connection', (ws) => {\n  console.log('Nouvelle connexion');\n\n  ws.on('message', (data) => {\n    const message = data.toString();\n    // Publication dans Redis pour toutes les instances\n    redisPub.publish(CHANNEL, JSON.stringify({ data: message }));\n  });\n});
\n\n

Avantages :

\n
    \n
  • Mise à l'échelle horizontale — ajoutez autant de serveurs que vous voulez
  • \n
  • Tolérance aux pannes — si une instance tombe, les autres continuent de fonctionner
  • \n
  • Bus de messages unifié via Redis Pub/Sub
  • \n
\n\n

2. Authentification et gestion des sessions

\n\n

Dans les applications de production, on ne peut pas faire confiance aux connexions non authentifiées. Implémentons la vérification des tokens via JWT lors de l'établissement de la connexion.

\n\n

Installons jsonwebtoken :

\n
npm install jsonwebtoken @types/jsonwebtoken
\n\n

Créons un middleware pour l'authentification WebSocket :

\n\n
import { IncomingMessage } from 'http';\nimport jwt from 'jsonwebtoken';\n\nconst JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';\n\ninterface AuthenticatedSocket extends WebSocket {\n  userId?: string;\n}\n\nfunction authenticate(ws: AuthenticatedSocket, req: IncomingMessage): boolean {\n  const url = new URL(req.url || '', 'http://localhost');\n  const token = url.searchParams.get('token');\n\n  if (!token) {\n    ws.close(4001, 'Token non fourni');\n    return false;\n  }\n\n  try {\n    const decoded = jwt.verify(token, JWT_SECRET) as { userId: string };\n    ws.userId = decoded.userId;\n    console.log(`Utilisateur ${decoded.userId} authentifié`);\n    return true;\n  } catch (err) {\n    ws.close(4002, 'Token invalide');\n    return false;\n  }\n}\n\n// Utilisation\nwss.on('connection', (ws: AuthenticatedSocket, req) => {\n  if (!authenticate(ws, req)) return;\n\n  ws.on('message', (data) => {\n    // Maintenant nous connaissons userId\n    console.log(`Message de ${ws.userId} : ${data}`);\n  });\n});
\n\n

Recommandations :

\n
    \n
  • Transmettez le token via un paramètre de requête ou des en-têtes lors de l'établissement de la connexion
  • \n
  • Utilisez des access-tokens à courte durée de vie et des refresh-tokens
  • \n
  • Stockez les sessions dans Redis

Blogs

Book Recommendations