Tutoriel : Créez une application de chat simple avec un hub de discussion

Dans ce tutoriel, vous construisez un simple flux de discussion en temps réel à l’aide d’un hub de chat Web PubSub.

Vous:

  • Configurez un serveur backend pour émettre des URL d’accès client
  • Connectez les clients à un hub de discussion Web PubSub
  • Créer une salle
  • Envoyer et recevoir des messages
  • Gérer l’adhésion à la salle

À la fin, vous bénéficiez d’une expérience de chat de travail soutenue par Azure Web PubSub.

Prerequisites

  • Un abonnement Azure
  • Node.js 18 ou version ultérieure

Créez une ressource Web PubSub avec un centre de discussion

Créez une ressource Azure Web PubSub et configurez un hub de discussion nommé demo-chat.

Installer des dépendances

Dépendances de serveur

npm install express @azure/web-pubsub @azure/web-pubsub-express

Dépendances du client

npm install @azure/web-pubsub-chat-client

Étape 1 : Créer le serveur backend

Le serveur backend est responsable de :

  • Authentification des utilisateurs
  • Émission des URL d’accès client

Code serveur

import express from 'express';
import { WebPubSubServiceClient } from '@azure/web-pubsub';
import { WebPubSubEventHandler } from '@azure/web-pubsub-express';

const hubName = 'demo-chat';
const port = process.env.PORT || 3000;

const connectionString = process.env.WEB_PUBSUB_CONNECTION_STRING;
if (!connectionString) {
  throw new Error('WEB_PUBSUB_CONNECTION_STRING is not set');
}

const app = express();

const serviceClient = new WebPubSubServiceClient(
  connectionString,
  hubName,
  { allowInsecureConnection: true }
);

Pourquoi cette étape existe-t-elle

Bien que le service Web PubSub prenne en charge les connexions anonymes, le modèle de production le plus courant utilise un modèle d’accès délivré par le serveur.

Votre serveur génère une URL d’accès client limitée dans le temps qui encode l’identité utilisateur et les permissions. Cette approche :

  • Garde les identifiants sécurisés
  • Permet à votre application de contrôler l’authentification et l’autorisation
  • En accord avec les attentes de sécurité des entreprises

Étape 2 : Ajouter un point de négociation

Le point de terminaison négocie renvoie une URL d’accès client que les clients de chat utilisent pour se connecter.

app.get('/negotiate', async (req, res) => {
  console.log(`received negotiate request: ${JSON.stringify(req.query)}`);

  const userId = req.query.userId;
  if (!userId) {
    return res.status(400).send('Missing userId');
  }

  const token = await serviceClient.getClientAccessToken({
    userId,
  });

  res.json({
    url: token.url,
  });
});

Pourquoi cette étape existe-t-elle

Les clients de chat doivent se connecter en tant qu’utilisateur spécifique.

Le point de négociation est celui où votre application :

  • Associe l’identité de l’application à un utilisateur du chat
  • Génère une URL d’accès temporaire à portée limitée
  • Décide qui est autorisé à se connecter

En production, ce point final est typiquement :

  • Vérifie l’authentification (cookies, en-têtes, jetons)
  • Applique les règles d’autorisation

Étape 3 : Démarrez le serveur

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});

Votre backend est désormais prêt à accepter les connexions clients.

Étape 4 : Connecter les clients au centre de discussion

Sur le client, récupérez les URL d’accès du serveur et connectez-vous au demo-chat hub.

import { ChatClient } from '@azure/web-pubsub-chat-client';

// Fetch a fresh client access URL from the negotiate endpoint.
const getClientAccessUrl = (userId) =>
  fetch(`/negotiate?userId=${userId}`)
    .then(r => r.json())
    .then(d => d.url);

// Option 1: start with a one-time client access URL.
const alice = await ChatClient.start(await getClientAccessUrl('alice'));
console.log(`Started as: ${alice.userId}`);

// Option 2: start with a credential so the client can refresh the URL itself.
const charlie = await ChatClient.start({
  getClientAccessUrl: () => getClientAccessUrl('charlie'),
});
console.log(`Started as: ${charlie.userId}`);

Pourquoi cette étape existe-t-elle

Le hub de discussion Web PubSub s’appuie sur le modèle de connexion Web PubSub. Voici cette étape d’authentification :

  • Établit une connexion en temps réel
  • Associe la connexion à une identité utilisateur
  • Permet de permettre des fonctionnalités spécifiques au chat telles que les salles et l’historique des messages

Étape 5 : Écoutez les événements de discussion

Inscrivez-vous pour recevoir des mises à jour en temps réel.

alice.on('message', (event) => {
  const msg = event.message;
  console.log(`Alice received: ${msg.createdBy}: ${msg.content.text}`);
});

alice.on('room-joined', (event) => {
  console.log(`Alice joined room: ${event.room.title}`);
});

charlie.on('message', (event) => {
  const msg = event.message;
  console.log(`Charlie received: ${msg.createdBy}: ${msg.content.text}`);
});

charlie.on('room-joined', (event) => {
  console.log(`Charlie joined room: ${event.room.title}`);
});

Le client de chat est un émetteur d’événements. Outre message et room-joined, vous pouvez être à l’écoute de room-left, member-joined, member-left, started et stopped. Utilisez off avec les mêmes arguments pour supprimer un écouteur.

Pourquoi cette étape existe-t-elle

Le chat est intrinsèquement axé sur les événements. Ces auditeurs permettent à votre application de :

  • Réagir aux messages entrants
  • Mettez à jour l’interface utilisateur lorsque les utilisateurs rejoignent les salles
  • Restez synchronisé sur plusieurs appareils ou onglets de navigateur

Étape 6 : Créez une pièce et envoyez des messages

Créez une salle et ajoutez les membres initiaux :

const room = await alice.createRoom('My Room', ['charlie']);

Envoyez un message à la salle :

await alice.sendToRoom(room.roomId, 'Hello!');

Les messages sont transmis en temps réel à tous les membres de la salle.

Pourquoi cette étape existe-t-elle

Les salles offrent une structure pour discuter :

  • Ils définissent qui reçoit les messages.
  • Ils conservent l’historique des messages.
  • Ils permettent au chat de s’étendre au-delà de la messagerie en tête-à-tête.

Étape 7 : Obtenir l’historique des messages

Récupérer les messages précédents d’un salon. listRoomMessages renvoie un itérateur asynchrone paginé, vous permettant d’itérer directement sur tous les messages :

for await (const msg of alice.listRoomMessages(room.roomId)) {
  console.log(`${msg.createdBy}: ${msg.content.text}`);
}

Ou chargez l’historique une page à la fois (par exemple, « chargez 50, puis 50 de plus en défilant ») :

const pages = alice.listRoomMessages(room.roomId).byPage({ maxPageSize: 50 });
const firstPage = await pages.next();
const messages = firstPage.value ?? [];

Pourquoi cette étape existe-t-elle

Les clients nouvellement connectés ont souvent besoin de contexte.

L’historique des messages permet à votre application de :

  • Afficher les messages existants
  • Reprendre la conversation après une reconnexion
  • Prise en charge de l’utilisation multi-appareils

Étape 8 : Gérer les membres de la salle

Ajoutez un utilisateur dans une pièce :

await alice.addUserToRoom(room.roomId, 'bob');

Retirer un utilisateur d’une pièce :

await alice.removeUserFromRoom(room.roomId, 'bob');

Les changements d’adhésion prennent effet immédiatement.

Étape 9 : Nettoyage

Lorsque le client n’a plus besoin de recevoir des messages :

await alice.stop();
await charlie.stop();

Ce que vous avez créé

Dans ce guide de démarrage rapide, vous :

  • Des URL d’accès client sécurisées émises depuis un serveur
  • Connexion des clients à un hub de discussion
  • A créé et rejoint des salons de discussion
  • Messages envoyés et reçus en temps réel
  • Historique des messages chargés
  • Appartenance à une salle gérée

Tout cela sans gérer les serveurs WebSocket, la logique de dispersion ou la persistance des messages.