#  ## Real-time API ## Infos générales * Développé par les-tilleuls.coop * Scop fondée par Kévin Dunglas * Beaucoup de contributions OpenSource, notamment sur Symfony * API Platform * Récemment, le protocole Vulcain (HTTP/2 Server Push) * Sorti fin 2018 pour la v0.1.0 * Une version gratuite et plusieurs versions payantes (+ de connexions concurrentes, rapidité accrue, ...) ## Infos techniques * C'est un protocole pour des communications rapides, en temps réel, fiables et économes en batterie * "Remplacement" des WebSockets API sur une couche plus élevée * Développé en Go * Compatible REST & GraphQL * Utilise les SSE (Server-Sent Events) ## Fonctionnement global  ## Setup rapide * Lancement d'un serveur Mercure en local via Docker : ```sh docker run \ -e MERCURE_PUBLISHER_JWT_KEY='!ChangeMe!' \ -e MERCURE_SUBSCRIBER_JWT_KEY='!ChangeMe!' \ -p 80:80 \ -p 443:443 \ dunglas/mercure ``` * Accès via la navigateur sur : https://localhost/.well-known/mercure ## Comment ça marche ? Subscriber * Via l'adresse précédente, erreur : `Missing "topic" parameter.` * Pourquoi ? * Fonctionne avec un système de Subscriber "classique" * En tant que Subscriber, on doit écouter un `topic` particulier * Résolution * Ajout de ce `topic` via un simple paramètre GET dans l'URL : https://localhost/.well-known/mercure?topic=https://example.com/message/1 * Ici, on écoute le `topic` "https://example.com/message/1", mais ce peut être n'importe quoi, même juste "test" ## Comment ça marche ? Publisher (1) * jwt.io > Debugger * Partie `Payload`: ```json { "mercure": { "publish": ["*"] } } ``` * Partie `Verify Signature`, on met le MDP de la commande Docker, ici `!ChangeMe!` * On récupère le token ## Comment ça marche ? Publisher (2) * Test en communication directe sans API * Dans un cas réel, c'est l'API qui se charge des appels Mercure 1. Tests via Postman * Requête POST sur : `https://localhost/.well-known/mercure` * Body de type `x-www-form-urlencoded` : * Données du body : * topic : `https://example.com/message/1` * data (string ou JSON) : `{"header": "BIEEEEERE", "body": "Hum... Une bonne pinte... Ou deux !!"}` * Partie `Authorization`, on met `Bearer ${TOKEN}` 2. Tests via CURL ```sh curl -d 'topic=https://example.com/message/1' \ -d 'data={"header": "BIEEEEERE", "body": "Hum... Une bonne pinte... Ou deux !!"}' \ -H 'Authorization: Bearer ${TOKEN}' \ -X POST https://localhost/.well-known/mercure ``` ## Résultat * Envoi d'un UUID * Dans notre onglet "Subscriber" `https://localhost/.well-known/mercure?topic=https://example.com/message/1`... ## "Ouais mais... Ton exemple il est nul !" * On tape directement via le navigateur, donc il tourne constamment * Ça ne s'utilise ja-mais comme ça dans une appli réelle ## Subscriber très simple en JS * Utilisation de l'interface EventSource (déf. Mozilla) ``` L'interface EventSource est utilisée afin de recevoir des évènements envoyés par le serveur. ``` * Ajout d'un objet EventHandler `.onmessage` appelé dès réception d'un message * Log de la partie data du message reçu dans la console ```js new EventSource( 'https://localhost/.well-known/mercure?topic=https://example.com/message/1', { withCredentials: false } ).onmessage = function(e) { console.log(e.data); } ``` * Packages NPM existants pour tous les frameworks JS pour utiliser les SSE simplement ## Exemple d'un publisher dans Symfony * Exemple le plus basique : ```php // src/Controller/PublishController.php namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Mercure\PublisherInterface; use Symfony\Component\Mercure\Update; class PublishController { public function __invoke(PublisherInterface $publisher): Response { $update = new Update( 'http://example.com/books/1', json_encode(['status' => 'OutOfStock']) ); // The Publisher service is an invokable object $publisher($update); return new Response('published!'); } } ``` ## Remarques / Questions ?
32. Baloon