Mercure is a protocol allowing to push data updates to web browsers and other HTTP clients in a convenient, fast, reliable and battery-efficient way. It is especially useful to publish real-time updates of resources served through web APIs, to reactive web and mobile apps.

The project launched by Kévin Dunglas, Software architect and API expert, creator of API platform and member of Symfony core team. The protocol has been published as an Internet Draft that is maintained in this repository.

Mercure implementation have been written in Golang, with native browser support, no lib nor SDK required and is compatible with all existing servers, even those who don’t support persistent connections (serverless architecture, PHP, FastCGI…). 

The protocol have a built-in connection re-establishment and state reconciliation, and JWT-based authorization mechanism, in addition of being performant, leverages HTTP/2 multiplexing.

Mercure is designed with hypermedia in mind, also supports GraphQL, support message encryption, and auto-discoverable through web linking. It can even work with old browsers (IE7+) using an EventSource polyfill with connection-less push in controlled environments (e.g. browsers on mobile handsets tied to specific carriers).

The reference hub implementation features include :

  • Fast, written in Go.
  • Works everywhere: static binaries and Docker images available
  • Automatic HTTP/2 and HTTPS (using Let’s Encrypt) support
  • CORS support, CSRF protection mechanism
  • Cloud Native, follows the Twelve-Factor App methodology
  • Open source (AGPL)

A first example is an implementation of a client who subscribe to get updates of any web page or any specific topic by URL in JavaScript, and the callback will be called every time an update is published :

// The subscriber subscribes to updates for the https://example.com/foo topic
// and to any topic matching https://example.com/books/{name}
const url = new URL('https://example.com/hub');
url.searchParams.append('topic', 'https://example.com/books/{id}');
url.searchParams.append('topic', 'https://example.com/users/dunglas');

const eventSource = new EventSource(url);

// The callback will be called every time an update is published
eventSource.onmessage = e => console.log(e); // do something with the payload

Sample usage is also available in PHP to post authorization data encoded in JWT :

<?php
define('DEMO_JWT', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM');
$postData = http_build_query([
    'topic' => 'http://localhost:3000/demo/books/1.jsonld',
    'data' => json_encode(['key' => 'updated value']),
]);
echo file_get_contents('http://localhost:3000/hub', false, stream_context_create(['http' => [
    'method'  => 'POST',
    'header'  => "Content-type: application/x-www-form-urlencoded\r\nAuthorization: Bearer ".DEMO_JWT,
    'content' => $postData,
]]));

The advantages of Mercure is that it doesn’t use WebSocket and plays better with HTTP/2, require no Javascript library or SDK, got lots of features, and finally is free software and open protocol. Open Source version is stateful according to Kevin, and it manage up to 65534 simultaneous connections per hub.

A managed version is also available, in beta, for high scalability, and allow to distribute load across multiple servers. The number of simultaneous connections per hub will be defiantly much higher.

A Symfony Mercure Component is available and allows to easily push updates to web browsers and other HTTP clients using the Mercure protocol. The component implement the “publisher” part of the protocol. The MercureBundle instead allows to easily push updates to web browsers and other HTTP clients in the Symfony full-stack framework, using the Mercure protocol.

More information at https://mercure.rocks

LEAVE A REPLY

Please enter your comment!
Please enter your name here