Chat-WebSocket --- Betrieb und Produktions-API

Zuletzt aktualisiert: Aug 31, 2026Abschnitt: Integrationen

Dieser Abschnitt beschreibt, wie Chat-(JSBOX-)WebSocket-Kanäle in der Mailoo-API funktionieren, welche Ereignisse sie übertragen und was Sie auf dem öffentlichen API-Host in Produktion konfigurieren müssen (Proxy, TLS, Skalierung).

Übersicht zur Chat-Integration (REST, Schlüssel, BFF): chat-widget{.interpreted-text role="doc"} und chat-widget-nextjs-example{.interpreted-text role="doc"}.

::: {.contents local=""} :::

Wo der WebSocket lebt

Der WebSocket hört nicht auf einem separaten Port. Derselbe Node.js-Prozess, der HTTP (Hono) bedient, erstellt einen http.Server und hängt bei upgrade Clients an ws (WebSocketServer mit noServer: true) an. Pfade sind fest im Servercode:

  • Eigentümer (Dashboard) --- /api/v1/chat/ws
  • Besucher (Widget) --- /api/v1/chat/visitor-ws

In Produktion verbinden sich Clients mit dem gleichen Host und Schema wie die REST-API, z. B. wss://api.example.com/api/v1/chat/ws?.... Sie benötigen keinen separaten „WebSocket-Port" --- HTTPS/WSS auf dem veröffentlichten API-Service (üblicherweise 443 hinter einem Load Balancer) reicht aus.

Zwei Kanäle und Authentifizierung

Eigentümer (Dashboard): /api/v1/chat/ws

Abfrageparameter: integrationId, token.

  • token --- Keycloak-Zugriffs-JWT (gleich wie Authorization: Bearer für REST). In der Entwicklung kann ein konfigurierter Bypass einen Dev-Token akzeptieren (wie in der App).
  • Nach dem upgrade überprüft die API den Benutzer und dass die Integration existiert, vom Typ JSBOX ist und diesem Benutzer gehört.
  • Bei Erfolg registriert sich der Client im In-Memory-Hub nach integrationId und erhält {"type":"connected","integrationId":"..."}.

Besucher: /api/v1/chat/visitor-ws

Abfrageparameter: projectUid, integrationId, sessionPublicId.

  • Kein API-Schlüssel: Vertrauen basiert auf einer bestehenden Chat-Session in der DB (erstellt durch die erste Webhook-Nachricht) mit übereinstimmender publicId, integrationId und project.uid.
  • Bei Erfolg --- Hub-Registrierung für integrationId + sessionPublicId, Antwort {"type":"connected","sessionPublicId":"..."}.

Hub und Ereignisse

Implementiert als In-Memory-Modul (Verbindungs-Maps pro Integration und pro Session). Wenn eine neue Chat-Nachricht erscheint (eingehend vom Besucher oder ausgehende Eigentümerantwort), sendet der Server JSON wie:

{
  "type": "chat.message",
  "payload": {
    "messageId": "...",
    "integrationId": "...",
    "sessionPublicId": "...",
    "messageType": "INBOUND|OUTBOUND",
    "content": "...",
    "senderEmail": "...",
    "senderName": null,
    "createdAt": "..."
  }
}

Clients verwenden dies, um die UI zu aktualisieren, ohne vollständiges REST-Polling. Wenn WebSocket nicht verfügbar ist, kann die App auf Polling zurückgreifen (wie in der Chat-Konsole oder im Widget).

Produktions-Checkliste (öffentliche Mailoo-API)

Checkliste für Teams, die die Mailoo-API im Internet veröffentlichen. Ein separater „WebSocket-Port" wird nicht publiziert: Sie benötigen einen korrekten Reverse Proxy, TLS und ein klares Skalierungs-Modell.

  1. Gleicher Origin wie REST

    Das Browser-Widget und das Dashboard erstellen URLs wie wss://<API_HOST>/api/v1/chat/.... Stellen Sie sicher, dass API_PUBLIC_URL / öffentliches DNS auf denselben Host zeigen, auf dem dieser Prozess läuft (oder einen stabilen Load Balancer davor).

  2. TLS und ``wss:``

    Auf einer HTTPS-Site muss das Widget WSS verwenden. Der Proxy benötigt gültige Zertifikate; der Pfad zur API entspricht normalem HTTPS.

  3. Proxy: Upgrade-Unterstützung

    Für /api/v1/chat/ws und /api/v1/chat/visitor-ws (und allgemein für die API, wenn WS dieselbe location teilt) benötigen Sie:

  • HTTP/1.1 zum Upstream;

  • Upgrade- und Connection-Header (typisches WebSocket-Muster);

  • erhöhte Lese-Timeouts für langlebige Verbindungen (Zehn-Minuten/Stunden), da der Proxy sonst ruhige Sockets trennt.

    Beispiel-nginx-Fragment (gleicher Upstream wie REST):

    location / {
      proxy_pass http://api_backend;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_read_timeout 3600s;
      proxy_send_timeout 3600s;
    }
    

    Stellen Sie sicher, dass Ihr Reverse Proxy (oder Cloud-Load-Balancer) WebSocket-Upgrade-/Connection-Header weiterleitet und lange Lese-/Sende-Timeouts auf der API-Location verwendet.

  1. Firewall / Sicherheitsgruppen

    Gleiche Regeln wie eine normale HTTPS-API (z. B. eingehend 443 zum Load Balancer). Ausgehend zu DB, Keycloak, S3 --- je nach Ihrer Architektur; WebSocket ändert das nicht.

  2. Mehrere API-Replikate (wichtig)

    Der aktuelle Chat-Hub lebt nur im Prozessspeicher. Eine Eigentümer-Verbindung auf Replikat A sieht keinen Broadcast, der auf Replikat B durchgeführt wird, wenn ein anderer Pod die Nachricht verarbeitet hat.

    Optionen:

  • vorübergehend ein einzelnes API-Replikat für zuverlässige Echtzeit betreiben;

  • oder Sticky Sessions (Client an Pod gebunden) per Cookie/IP auf dem Load Balancer aktivieren --- das hilft nur, wenn Nachrichten-Erstellungs-Webhooks und beide WebSockets auf derselben Instanz landen (unzuverlässig bei mehreren Workern);

  • echte horizontale Echtzeit-Skalierung benötigt einen gemeinsamen Broker (Redis Pub/Sub usw.) --- nicht implementiert in der aktuellen Codebasis.

    Dokumentieren Sie die gewählte Strategie in Ihrem Produktions-Runbook.

  1. Website-Seite (nicht die API)

    Das Next.js-BFF und Umgebungsvariablen wie MAILOO_CHAT_WS_ORIGIN / API-Basis müssen auf den öffentlichen API-Host zeigen, der WSS bereitstellt. Das wird auf der Website-App konfiguriert, nicht als separater WebSocket-Veröffentlichungsschritt.

Kurzzusammenfassung


Frage Antwort


Separater WebSocket-Port? Nein --- gleicher Service und Pfad wie REST (über 443 und den Proxy).

Was muss der Proxy unterstützen? Upgrade/WebSocket, lange Timeouts, TLS für wss.

Etwas außer HTTP(S) freizugeben? Nein, wenn die API bereits über HTTPS veröffentlicht ist.

Mehrere API-Pods? In-Memory-Hub: einzelnes Replikat, Sticky Sessions oder ein zukünftiger Event-Bus.

Siehe auch

  • chat-widget{.interpreted-text role="doc"} --- REST, Schlüssel, CORS, Sessions
  • chat-widget-nextjs-example{.interpreted-text role="doc"} --- Next.js-BFF und WebSocket-Origin-Umgebung
  • OpenAPI: https://api.mailoo.app/docs/v1