Skip to main content
Le MercureBroadcaster présenté ici a été ajouté dans la PR #61474 de laravel/framework (mergée le 10 septembre 2026). Au moment de la rédaction, il ne fait pas encore partie d’une release taguée et n’est pas mentionné dans la documentation officielle. Cette page est un aperçu basé sur le code source et les docblocks — vérifiez le changelog de laravel/framework avant de vous y fier en production.

Vue d’ensemble

La couche broadcasting de Laravel a longtemps proposé Reverb, Pusher et Ably comme drivers « WebSocket natifs ». Une nouvelle valeur mercure vient d’être ajoutée à config/broadcasting.php. Mercure est un protocole temps réel bâti sur Server-Sent Events (SSE) plutôt que sur une connexion WebSocket bidirectionnelle. Il se comporte davantage comme du long-polling HTTP/1.1 ou HTTP/2, ce qui lui confère plusieurs propriétés distinctes :
  • Il traverse de manière transparente l’infrastructure HTTP habituelle (reverse proxies, CDN, load balancers).
  • Les clients peuvent être implémentés uniquement avec l’API EventSource du navigateur — aucune bibliothèque cliente dédiée n’est nécessaire.
  • FrankenPHP embarque un hub Mercure intégré, donc aucune infrastructure supplémentaire n’est requise pour l’essayer.

La nouvelle valeur driver

Le commentaire listant les drivers supportés en tête de config/broadcasting.php mentionne désormais mercure :
Un exemple de configuration de connexion est également fourni :
Si url est omis, le driver bascule automatiquement sur le hub Mercure intégré à FrankenPHP (la fonction mercure_publish()). Cette décision est prise dans CreatesMercureDrivers::mercure() :
Lorsque vous utilisez un hub externe, url doit pointer vers l’API d’administration utilisée pour la publication, tandis que public_url correspond à l’URL à laquelle le navigateur se connecte. Cette séparation permet des configurations où la publication passe par un réseau interne (par exemple Docker Compose) alors que seule l’URL publique est exposée au navigateur.

Tokens de publication et d’abonnement séparés

Mercure est un protocole de contrôle d’accès basé sur JWT. Le trait CreatesMercureDrivers construit deux fabriques de tokens distinctes : l’une pour la publication (serveur → hub), l’autre pour l’abonnement (navigateur → hub) :
  • secret, publish_secret et subscribe_secret peuvent chacun être configurés indépendamment, avec un repli sur secret.
  • algorithm, publish_algorithm et subscribe_algorithm peuvent de la même façon être définis par côté (valeur par défaut HS256).
  • HS256 exige un secret d’au moins 32 octets, HS384 au moins 48 et HS512 au moins 64 ; dans le cas contraire, une InvalidArgumentException est levée.
Le token de publication porte Grant::ACTION_PUBLISH pour tous les topics (*) et est mémoïsé par CachingTokenProvider, afin de ne pas régénérer un nouveau JWT à chaque appel de broadcast. La plus grande différence architecturale par rapport aux drivers WebSocket est que l’autorisation côté abonné est gérée par un seul cookie. MercureBroadcaster::auth() accepte un tableau channel_names (plafonné à 100 par requête), évalue l’autorisation canal par canal, puis émet un unique cookie d’autorisation qui les couvre tous :
Point crucial : un seul canal refusé ne fait pas échouer la réponse entière — il est marqué denied: true dans la charge utile pendant que les autres canaux autorisés continuent de fonctionner. Cela compte parce que Mercure multiplexe de nombreux topics sur une seule connexion EventSource : les canaux peuvent donc être ajoutés ou retirés en cours de session sans détruire la connexion. Les canaux Presence reçoivent une forme de Grant différente de celle des canaux private/private-encrypted classiques, ciblant le pattern d’URL d’abonnement utilisé par l’API Subscription de Mercure.

Canaux chiffrés de bout en bout

Les canaux préfixés par private-encrypted- sont traités comme chiffrés de bout en bout (E2EE) — ce qui signifie que même le hub Mercure lui-même ne voit jamais la charge utile. Cette capacité n’existe pas dans les drivers Pusher et Reverb actuels. Définir une encryption_key de 32 octets encodée en base64 active le ChannelEncrypter, qui empaquette le nom de l’événement, la charge utile et le socket ID dans un JWE (JSON Web Encryption) avant l’envoi par broadcast(). Le hub ne relaie donc que des octets chiffrés.
Les abonnés déchiffrent côté navigateur à l’aide du champ jwk (JSON Web Key) renvoyé dans la réponse de auth() — un échange de clé hors bande recommandé par la spécification Mercure, de sorte que le hub n’apprend jamais la clé.
Les canaux Presence ne peuvent pas être chiffrés, puisque leur liste de membres transite par conception via l’API Subscription du hub — ce qui est incompatible avec l’E2EE.

Whispers (messages directs entre clients)

Lorsque client_events est activé (valeur par défaut), chaque canal protégé se voit attribuer un « topic whisper » dédié auquel les abonnés peuvent publier :
Le topic propre du canal reste réservé au serveur, de sorte qu’un client ne peut jamais forger un événement paraissant venir du serveur. Cela reprend l’idée des « client events » de Pusher, mais garde l’autorisation clairement séparée grâce à des topics distincts.

Nommage des topics

Comme les hubs Mercure sont souvent partagés entre plusieurs applications, les topics sont placés sous un espace de noms topic_prefix afin d’éviter les collisions. La valeur par défaut est :
.alt est un suffixe DNS réservé et non résolvable (RFC 9476), il ne peut donc jamais entrer en collision avec un domaine réel. Les noms de canaux sont encodés URL selon la RFC 3986 dans un unique segment de chemin :
Un hub Mercure tourne fréquemment sur un sous-domaine différent de celui de l’application (par exemple mercure.example.com vs app.example.com) ; l’échec à résoudre un domaine de cookie commun lève donc une exception descriptive :
Si vous utilisez un nom de cookie préfixé par __Secure- ou __Host-, le driver vérifie également au démarrage que public_url est bien en HTTPS :

Choisir entre Reverb, Pusher/Ably et Mercure

Mercure convient bien lorsque vous n’avez pas besoin d’une connexion bidirectionnelle persistante — notifications, indicateurs de progression ou cas d’usage de type chat, essentiellement du serveur vers le client. Si vous utilisez déjà FrankenPHP, il fonctionne sans aucune infrastructure supplémentaire.

Pages liées

Dernière modification le 13 septembre 2026