Skip to main content
Der hier beschriebene MercureBroadcaster wurde mit laravel/framework PR #61474 hinzugefügt (gemergt am 10. September 2026). Zum Zeitpunkt der Erstellung ist er noch in keinem getaggten Release enthalten und auf der offiziellen Dokumentationsseite nicht dokumentiert. Diese Seite ist eine Vorabbetrachtung auf Basis des Quellcodes und der Docblocks — prüfen Sie das Changelog von laravel/framework, bevor Sie ihn produktiv einsetzen.

Überblick

Die Broadcasting-Schicht von Laravel liefert seit Langem Reverb, Pusher und Ably als „WebSocket-native” Treiber. Neu hinzugekommen ist der Treiberwert mercure in config/broadcasting.php. Mercure ist ein Echtzeitprotokoll, das auf Server-Sent Events (SSE) statt auf einer bidirektionalen WebSocket-Verbindung aufsetzt. Es verhält sich eher wie Long Polling über HTTP/1.1 oder HTTP/2, woraus sich einige besondere Eigenschaften ergeben:
  • Es passiert reguläre HTTP-Infrastruktur (Reverse Proxies, CDNs, Load Balancer) transparent.
  • Clients lassen sich allein mit der EventSource-API des Browsers implementieren — eine dedizierte Client-Bibliothek ist nicht erforderlich.
  • FrankenPHP bringt einen eingebauten Mercure-Hub mit, sodass zum Ausprobieren keine zusätzliche Infrastruktur nötig ist.

Der neue driver-Wert

Der Kommentar mit den unterstützten Treibern am Anfang von config/broadcasting.php listet nun auch mercure auf:
Eine Beispielkonfiguration für die Verbindung wird ebenfalls mitgeliefert:
Wird url weggelassen, fällt der Treiber auf den in FrankenPHP eingebauten Mercure-Hub (die Funktion mercure_publish()) zurück. Diese Entscheidung fällt in CreatesMercureDrivers::mercure():
Betreiben Sie einen externen Hub, sollte url auf die Management-API zum Publizieren zeigen, während public_url die URL ist, mit der sich der Browser verbindet. Diese Trennung unterstützt Setups, in denen das Publizieren über ein internes Netzwerk (etwa Docker Compose) läuft, während nur die öffentliche URL für den Browser sichtbar ist.

Getrennte Publish- und Subscribe-Tokens

Mercure ist ein JWT-basiertes Protokoll zur Zugriffskontrolle. Der Trait CreatesMercureDrivers baut getrennte Token-Factories für das Publizieren (Server → Hub) und das Abonnieren (Browser → Hub) auf:
  • secret, publish_secret und subscribe_secret lassen sich jeweils unabhängig konfigurieren und fallen auf secret zurück.
  • Analog können algorithm, publish_algorithm und subscribe_algorithm seitengetrennt gesetzt werden (Standard: HS256).
  • HS256 verlangt ein Secret von mindestens 32 Byte, HS384 mindestens 48 und HS512 mindestens 64; andernfalls wird eine InvalidArgumentException geworfen.
Das Publish-Token trägt Grant::ACTION_PUBLISH für alle Topics (*) und wird vom CachingTokenProvider memoisiert, sodass nicht bei jedem einzelnen Broadcast-Aufruf ein neues JWT erzeugt wird. Der größte architektonische Unterschied zu den WebSocket-Treibern besteht darin, dass die Autorisierung der Abonnenten über ein einziges Cookie abgewickelt wird. MercureBroadcaster::auth() nimmt ein channel_names-Array entgegen (begrenzt auf 100 Einträge pro Anfrage), prüft die Autorisierung pro Kanal und stellt anschließend ein einzelnes Autorisierungs-Cookie aus, das alle Kanäle abdeckt:
Entscheidend ist: Ein einzelner abgelehnter Kanal lässt die gesamte Antwort nicht scheitern — er wird in der Antwortnutzlast lediglich mit denied: true markiert, während die übrigen autorisierten Kanäle weiterhin funktionieren. Das ist wichtig, weil Mercure viele Topics über eine einzige EventSource-Verbindung multiplext, sodass Kanäle mitten in einer Sitzung hinzugefügt oder entfernt werden können, ohne die Verbindung abbauen zu müssen. Presence-Kanäle erhalten eine andere Grant-Form als reguläre private- oder private-encrypted-Kanäle; sie zielen auf das Subscribe-URL-Muster ab, das die Subscription API von Mercure verwendet.

Ende-zu-Ende-verschlüsselte Kanäle

Kanäle mit dem Präfix private-encrypted- werden als Ende-zu-Ende-verschlüsselt (E2EE) behandelt — das bedeutet, dass selbst der Mercure-Hub die Nutzdaten nie zu sehen bekommt. Diese Fähigkeit bieten die bestehenden Pusher- und Reverb-Treiber nicht. Wird ein base64-kodierter, 32 Byte langer encryption_key gesetzt, aktiviert das den ChannelEncrypter. Dieser verpackt Eventnamen, Nutzdaten und Socket-ID zu einer JWE (JSON Web Encryption), bevor broadcast() sie versendet. Der Hub leitet ausschließlich verschlüsselte Bytes weiter.
Abonnenten entschlüsseln im Browser mithilfe des jwk-Feldes (JSON Web Key), das die auth()-Antwort zurückliefert — ein von der Mercure-Spezifikation empfohlener Out-of-Band-Schlüsselaustausch, bei dem der Hub den Schlüssel niemals erfährt.
Presence-Kanäle können nicht verschlüsselt werden, da ihre Mitgliederliste konstruktionsbedingt über die Subscription-API des Hubs läuft — und das ist mit E2EE nicht vereinbar.

Whispers (direkte Nachrichten zwischen Clients)

Ist client_events aktiviert (Standardwert), erhält jeder geschützte Kanal ein eigenes „Whisper-Topic”, auf dem Abonnenten publizieren dürfen:
Das eigentliche Topic des Kanals bleibt serverseitig, sodass ein Client kein vom Server ausgehendes Event fälschen kann. Das Prinzip ähnelt dem „Client Events”-Feature von Pusher, hält die Autorisierung durch die getrennten Topics aber sauber voneinander getrennt.

Topic-Benennung

Da Mercure-Hubs häufig von mehreren Anwendungen gemeinsam genutzt werden, werden Topics unter einem topic_prefix in einem Namensraum abgelegt, um Kollisionen zu vermeiden. Der Standardwert lautet:
.alt ist ein reservierter, nicht auflösbarer DNS-Suffix (RFC 9476) und kann daher niemals mit einer realen Domain kollidieren. Kanalnamen werden gemäß RFC 3986 URL-kodiert in ein einzelnes Pfadsegment gepackt:
Da ein Mercure-Hub häufig auf einer anderen Subdomain läuft als die Anwendung (etwa mercure.example.com gegenüber app.example.com), wirft der Treiber bei einer misslungenen Auflösung einer gemeinsamen Cookie-Domain eine aussagekräftige Exception:
Verwenden Sie einen Cookie-Namen mit dem Präfix __Secure- oder __Host-, prüft der Treiber beim Booten außerdem, ob public_url per HTTPS ausgeliefert wird:

Wahl zwischen Reverb, Pusher/Ably und Mercure

Mercure eignet sich gut, wenn Sie keine dauerhafte bidirektionale Verbindung benötigen — für Benachrichtigungen, Fortschrittsanzeigen oder chatartige Anwendungsfälle, die vorwiegend vom Server zum Client fließen. Wenn Sie bereits FrankenPHP einsetzen, funktioniert Mercure ganz ohne zusätzliche Infrastruktur.

Verwandte Seiten

Zuletzt geändert am 13. September 2026