|
| 1 | +# Pushing Live Updates Using the Mercure Protocol |
| 2 | + |
| 3 | +API Platform can automatically send real time updates to the currently connected clients (webapps, mobile apps...) using [the Mercure protocol](https://mercure.rocks). |
| 4 | + |
| 5 | +> *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. |
| 6 | +> - https://mercure.rocks |
| 7 | +
|
| 8 | +API Platform detects changes made to your Doctrine entities, and sends the updated resources to the Mercure hub. |
| 9 | +Then, the Mercure hub dispatches the updates to all connected clients using [Server-sent Events (SSE)](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events). |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +## Installing the Mercure Support |
| 14 | + |
| 15 | +The Mercure support is already installed, configured and enabled in [the official distribution](../distribution/index.md). |
| 16 | +If you use the distribution, you have nothing more to do, and you can jump to the next section. |
| 17 | + |
| 18 | +If you have installed API Platform using another method (such as `composer require api`), you need to install a Mercure hub, and the [Symfony MercureBundle](https://github.com/symfony/mercure-bundle): |
| 19 | + |
| 20 | +First, [download and run a Mercure hub](https://github.com/dunglas/mercure#hub-implementation). |
| 21 | +Then, install the Symfony bundle: |
| 22 | + |
| 23 | + $ composer require mercure |
| 24 | + |
| 25 | +Finally, 3 environment variables [must be set](https://symfony.com/doc/current/configuration/external_parameters.html): |
| 26 | + |
| 27 | +* `MERCURE_PUBLISH_URL`: the URL that must be used by API Platform to publish updates to your Mercure hub (can be an internal or a public URL) |
| 28 | +* `MERCURE_SUBSCRIBE_URL`: the **public** URL of the Mercure hub that clients will use to subscribe to updates |
| 29 | +* `MERCURE_JWT`: a valid Mercure [JSON Web Token (JWT)](https://jwt.io/) allowing API Platform to publish updates to the hub |
| 30 | + |
| 31 | +The JWT **must** contain a `mercure.publish` property containing an array of targets. |
| 32 | +This array can be empty to allow publishing anonymous updates only. |
| 33 | +[Example publisher JWT](https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM) (demo key: `!UnsecureChangeMe!`). |
| 34 | + |
| 35 | +[Learn more about Mercure authorization.](https://github.com/dunglas/mercure/blob/master/spec/mercure.md#authorization) |
| 36 | + |
| 37 | +## Pushing the API Updates |
| 38 | + |
| 39 | +Use the `mercure` attribute to hint API Platform that it must dispatch the updates regarding the given resources to the Mercure hub: |
| 40 | + |
| 41 | +```php |
| 42 | +<?php |
| 43 | +// api/src/Entity/Book.php |
| 44 | + |
| 45 | +namespace App\Entity; |
| 46 | + |
| 47 | +use ApiPlatform\Core\Annotation\ApiResource; |
| 48 | + |
| 49 | +/** |
| 50 | + * @ApiResource(mercure=true) |
| 51 | + */ |
| 52 | +class Book |
| 53 | +{ |
| 54 | + // ... |
| 55 | +} |
| 56 | +``` |
| 57 | + |
| 58 | +Then, every time an object of this type is created, updated or deleted, the new version is sent to all connected clients through the Mercure hub. |
| 59 | +If the resource has been deleted, only the (now deleted) IRI of the resource is sent to the clients. |
| 60 | + |
| 61 | +In addition, API Platform automatically adds a `Link` HTTP header to all responses related to this resource class. |
| 62 | +This header allows smart clients to automatically discover the Mercure hub. |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +Clients generated using [the API Platform Client Generator](../client-generator/index.md) will use this capability to automatically subscribe to Mercure updates when available: |
| 67 | + |
| 68 | + |
| 69 | + |
| 70 | +[Learn how to use the discovery capabilities of Mercure in your own clients](https://github.com/dunglas/mercure#examples). |
| 71 | + |
| 72 | +## Dispatching Private Updates (Authorized Mode) |
| 73 | + |
| 74 | +Mercure allows to dispatch [private updates, that will be received only by authorized clients](https://github.com/dunglas/mercure/blob/master/spec/mercure.md#authorization). |
| 75 | +To receive this kind of updates, the client must hold a JWT containing at least one *target* marking the update. |
| 76 | + |
| 77 | +Then, hint API Platform to dispatch the updates only to the selected targets: |
| 78 | + |
| 79 | +```php |
| 80 | +<?php |
| 81 | +// api/src/Entity/Book.php |
| 82 | + |
| 83 | +namespace App\Entity; |
| 84 | + |
| 85 | +use ApiPlatform\Core\Annotation\ApiResource; |
| 86 | + |
| 87 | +/** |
| 88 | + * @ApiResource(mercure={"a-group", "another-group"}) |
| 89 | + */ |
| 90 | +class Book |
| 91 | +{ |
| 92 | + // ... |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +It's also possible to execute an *expression* (using the [Symfony Expression Language component](https://symfony.com/doc/current/components/expression_language.html)), to generate a dynamic list of targets: |
| 97 | + |
| 98 | +```php |
| 99 | +<?php |
| 100 | +// api/src/Entity/Book.php |
| 101 | + |
| 102 | +namespace App\Entity; |
| 103 | + |
| 104 | +use ApiPlatform\Core\Annotation\ApiResource; |
| 105 | + |
| 106 | +/** |
| 107 | + * @ApiResource(mercure="object.owners") |
| 108 | + */ |
| 109 | +class Book |
| 110 | +{ |
| 111 | + public $owners = []; |
| 112 | + // ... |
| 113 | +} |
| 114 | +``` |
0 commit comments