Overzicht
De broadcastinglaag van Laravel biedt al lange tijd de “WebSocket-native” drivers Reverb, Pusher en Ably. Aanconfig/broadcasting.php is nu een nieuwe driverwaarde mercure toegevoegd.
Mercure is een realtime protocol dat op Server-Sent Events (SSE) is gebouwd in plaats van op een bidirectionele WebSocket-verbinding. Het gedraagt zich meer als long-polling over HTTP/1.1 of HTTP/2, wat een aantal onderscheidende eigenschappen oplevert:
- Het gaat transparant door gewone HTTP-infrastructuur heen (reverse proxies, CDN’s, load balancers).
- Clients kunnen worden geïmplementeerd met alleen de
EventSource-API van de browser — er is geen aparte clientbibliotheek nodig. - FrankenPHP heeft een ingebouwde Mercure-hub, dus je hebt geen extra infrastructuur nodig om ermee te experimenteren.
De nieuwe driver-waarde
In de commentaarregel bovenaan config/broadcasting.php met ondersteunde drivers staat nu ook mercure:
url weglaat, valt de driver terug op de ingebouwde Mercure-hub van FrankenPHP (de functie mercure_publish()). Die beslissing wordt genomen in CreatesMercureDrivers::mercure():
url verwijzen naar de management-API die voor publishen wordt gebruikt, terwijl public_url de URL is waarmee de browser verbinding maakt. Door beide te splitsen worden opstellingen ondersteund waarbij publishen via een intern netwerk gebeurt (bijvoorbeeld Docker Compose) en alleen de publieke URL naar de browser wordt blootgesteld.
Gescheiden publish- en subscribe-tokens
Mercure is een op JWT gebaseerd protocol voor toegangscontrole. De traitCreatesMercureDrivers bouwt aparte token-factories voor publishen (server → hub) en subscriben (browser → hub):
secret,publish_secretensubscribe_secretkunnen onafhankelijk van elkaar worden geconfigureerd; bij afwezigheid vallen ze terug opsecret.algorithm,publish_algorithmensubscribe_algorithmkunnen op dezelfde manier per kant worden ingesteld (standaardHS256).- HS256 vereist een secret van minimaal 32 bytes, HS384 minimaal 48 en HS512 minimaal 64; anders wordt een
InvalidArgumentExceptiongegooid.
Grant::ACTION_PUBLISH voor alle topics (*) en wordt gememoïseerd door CachingTokenProvider, zodat er niet bij elke afzonderlijke broadcast-aanroep een nieuwe JWT hoeft te worden gegenereerd.
Kanaalautorisatie via één enkele cookie
Het grootste architecturale verschil met de WebSocket-drivers is dat de autorisatie van abonnees via één cookie verloopt.MercureBroadcaster::auth() accepteert een array channel_names (met een limiet van 100 per request), beoordeelt de autorisatie per kanaal en geeft vervolgens één enkele autorisatiecookie uit die alle kanalen omvat:
denied: true, terwijl de overige geautoriseerde kanalen gewoon blijven werken. Dat is belangrijk omdat Mercure meerdere topics multiplext over één EventSource-verbinding, zodat kanalen halverwege een sessie kunnen worden toegevoegd of verwijderd zonder de verbinding te verbreken.
Presence-kanalen krijgen een andere Grant-vorm dan gewone private- of private-encrypted-kanalen, gericht op het subscribe-URL-patroon dat door Mercure’s Subscription-API wordt gebruikt.
End-to-end versleutelde kanalen
Kanalen met het prefixprivate-encrypted- worden behandeld als end-to-end versleuteld (E2EE) — dat betekent dat zelfs de Mercure-hub zelf de payload nooit te zien krijgt. Dit is een mogelijkheid die de bestaande Pusher- en Reverb-drivers niet bieden.
Als je een base64-gecodeerde encryption_key van 32 bytes instelt, wordt de ChannelEncrypter geactiveerd. Die verpakt de eventnaam, de payload en het socket-ID in een JWE (JSON Web Encryption) voordat broadcast() het verstuurt. De hub geeft alleen versleutelde bytes door.
jwk-veld (JSON Web Key) dat door de auth()-respons wordt teruggegeven — een out-of-band-sleuteluitwisseling die door de Mercure-specificatie wordt aanbevolen, waardoor de hub de sleutel nooit leert kennen.
Presence-kanalen kunnen niet worden versleuteld, omdat hun ledenlijst per ontwerp via de Subscription-API van de hub loopt — dat is onverenigbaar met E2EE.
Whispers (directe berichten tussen clients)
Wanneerclient_events is ingeschakeld (de standaard), krijgt elk beschermd kanaal een speciaal “whisper-topic” toegewezen waar abonnees op mogen publishen:
Naamgeving van topics
Omdat Mercure-hubs vaak door meerdere applicaties worden gedeeld, worden topics genamespaced onder eentopic_prefix om botsingen te voorkomen. De standaardwaarde is:
.alt is een gereserveerd, niet-resolvbaar DNS-suffix (RFC 9476), dus het kan nooit botsen met een echt domein. Kanaalnamen worden URL-encoded volgens RFC 3986 en in één padsegment gestopt:
Cookiedomein en foutmeldingen
Omdat een Mercure-hub vaak op een ander subdomein draait dan de applicatie (bijvoorbeeldmercure.example.com versus app.example.com), wordt er een beschrijvende exception gegooid als er geen gedeeld cookiedomein kan worden bepaald:
__Secure- of __Host-, controleert de driver bij het opstarten ook of public_url HTTPS is:
Kiezen tussen Reverb, Pusher/Ably en Mercure
Mercure is een goede keuze wanneer je geen persistente bidirectionele verbinding nodig hebt — denk aan notificaties, voortgangsupdates of chat-achtige use cases die vooral van server naar client gaan. Als je al FrankenPHP draait, werkt het zelfs zonder enige extra infrastructuur.
Gerelateerde pagina’s
- Basis van broadcasting
- Laravel Cloud (op FrankenPHP gebaseerde runtime)