Tutorial: Baue eine einfache Chat-App mit einem Chat-Hub

In diesem Tutorial baust du einen einfachen Echtzeit-Chatfluss mit einem Web PubSub Chat-Hub auf.

Sie:

  • Richten Sie einen Backend-Server ein, um Client-Zugriffs-URLs auszugeben
  • Verbinden Sie Clients mit einem Web PubSub Chat-Hub
  • Erstellen eines Raums
  • Senden und Empfangen von Nachrichten
  • Raummitgliedschaft verwalten

Am Ende hast du eine funktionierende Chat-Erfahrung, unterstützt von Azure Web PubSub.

Voraussetzungen

  • Ein Azure-Abonnement
  • Node.js 18 oder höher

Erstellen Sie eine Web-PubSub-Ressource mit einem Chat-Hub

Erstellen Sie eine Azure Web PubSub-Ressource und konfigurieren Sie einen Chat-Hub namens demo-chat.

Abhängigkeiten installieren

Serverabhängigkeiten

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

Klientabhängigkeiten

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

Schritt 1: Erstellen Sie den Backend-Server

Der Backend-Server ist verantwortlich für:

  • Authentifizieren von Benutzern
  • Vergabe von Client-Zugriffs-URLs

Servercode

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 }
);

Warum dieser Schritt existiert

Obwohl der Web PubSub-Dienst anonyme Verbindungen unterstützt, verwendet das gebräuchlichste Produktionsmuster ein serverfreigegebenes Zugriffsmodell.

Ihr Server erzeugt eine zeitlich begrenzte Client-Zugriffs-URL , die die Benutzeridentität und Berechtigungen kodiert. Dieser Ansatz:

  • Sichert die Zugangsdaten
  • Ermöglicht es Ihrer App, Authentifizierung und Autorisierung zu steuern
  • Entspricht den Unternehmenssicherheitserwartungen

Schritt 2: Fügen Sie einen Negotiate-Endpunkt hinzu

Der Negotiate-Endpunkt liefert eine Client-Zugriffs-URL, die Chat-Clients zur Verbindung verwenden.

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,
  });
});

Warum dieser Schritt existiert

Chat-Clients müssen sich als spezifischer Nutzer verbinden.

Der „negotiate“-Endpunkt ist der Punkt, an dem Ihre Anwendung:

  • Ordnet die Identität auf Anwendungsebene einem Chatbenutzer zu
  • Gibt eine begrenzte, temporäre Zugriffs-URL heraus
  • Entscheidet, wer sich verbinden darf.

In der Produktion ist dieser Endpunkt typischerweise:

  • Verifiziert Authentifizierung (Cookies, Header, Token)
  • Setzt Autorisierungsregeln durch

Schritt 3: Starte den Server

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

Ihr Backend ist jetzt bereit, Kundenverbindungen anzunehmen.

Schritt 4: Verbinden Sie Clients mit dem Chat-Hub

Auf dem Client rufen Sie die Zugriffs-URLs vom Server ab und melden sich beim demo-chat Hub an.

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}`);

Warum dieser Schritt existiert

Der Web PubSub Chat-Hub baut auf dem Web-PubSub-Verbindungsmodell auf. Dieser Authentifizierungsschritt:

  • Stellt eine Echtzeitverbindung her
  • Verknüpft die Verbindung mit einer Benutzeridentität
  • Aktiviert chatspezifische Funktionen wie Räume und Nachrichtenverlauf

Schritt 5: Hören Sie auf Chat-Events

Registrieren Sie Zuhörer, um Echtzeit-Updates zu erhalten.

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}`);
});

Der Chat-Client ist ein Ereignisemitter. Zusätzlich zu message und room-joined können Sie auf room-left, member-joined, member-left, started und stopped hören. Verwenden Sie off mit den gleichen Argumenten, um einen Listener zu entfernen.

Warum dieser Schritt existiert

Chat ist von Natur aus ereignisgesteuert. Diese Zuhörer ermöglichen es Ihrer Anwendung:

  • Reagieren Sie auf eingehende Nachrichten
  • Aktualisieren Sie die Benutzeroberfläche, wenn Benutzer Räume betreten
  • Bleiben Sie über mehrere Geräte oder Browser-Tabs hinweg synchronisiert

Schritt 6: Erstelle einen Raum und sende Nachrichten

Erstelle einen Raum und füge erste Mitglieder hinzu:

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

Senden Sie eine Nachricht an den Raum:

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

Nachrichten werden in Echtzeit an alle Raummitglieder übermittelt.

Warum dieser Schritt existiert

Die Räume bieten eine Struktur für Gespräche:

  • Sie bestimmen, wer Nachrichten empfängt.
  • Sie behalten den Nachrichtenverlauf bei.
  • Sie ermöglichen es, den Chat über Eins-zu-Eins-Nachrichten hinaus zu skalieren.

Schritt 7: Erhalten Sie die Nachrichtenhistorie

Rufe frühere Nachrichten aus einem Raum ab. listRoomMessages gibt einen seitenweisen asynchronen Iterator zurück, sodass du direkt über jede Nachricht iterieren kannst:

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

Oder den Verlauf Seite für Seite laden (zum Beispiel „50 laden, dann 50 weitere beim Hochscrollen“):

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

Warum dieser Schritt existiert

Neu verbundene Kunden benötigen oft Kontext.

Der Nachrichtenverlauf ermöglicht es Ihrer App:

  • Bestehende Nachrichten darstellen
  • Chat nach der Wiederverbindung wieder aufnehmen
  • Unterstützung der Nutzung von mehreren Geräten

Schritt 8: Raummitglieder verwalten

Fügen Sie einen Benutzer zu einem Raum hinzu:

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

Entfernen Sie einen Benutzer aus einem Raum:

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

Mitgliedschaftsänderungen treten sofort in Kraft.

Schritt 9: Aufräumen

Wenn der Client keine Nachrichten mehr empfangen muss:

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

Was Sie erstellt haben

In dieser Schnellstartanleitung führen Sie die folgenden Schritte aus:

  • Sichere Client-Zugriffs-URLs von einem Server ausgegeben.
  • Mit einem Chat-Hub verbundene Clients
  • Erstellte und beigetretene Chaträume
  • Nachrichten in Echtzeit gesendet und empfangen
  • Geladener Nachrichtenverlauf
  • Verwaltete Raummitgliedschaft

Und das alles ohne die Verwaltung von WebSocket-Servern, Fan-Out-Logik oder Nachrichtenpersistenz.