Laravel Mercure Broadcaster

repository·master·Indexed 41 days ago

https://github.com/mvanduijker/laravel-mercure-broadcaster

A Laravel broadcaster implementation for Mercure that enables Server-Sent Events (SSE) integration. It allows developers to broadcast events to public and private channels using the Mercure protocol, supporting JWT-based authentication for secure private channels.

Tokens
1.8K
Snippets
6
Records
8
Agent score
52%

What's inside Laravel Mercure Broadcaster

  1. Broadcast public events via Mercure

    master

    To broadcast public events, create an event class that implements the ShouldBroadcast interface. In the broadcastOn() method, return a Channel instance using a URI as the channel name.

    On the frontend, use the EventSource API, appending the topic as a query parameter to the Mercure URL.

    // Backend: Event definition
    class NewsItemCreated implements ShouldBroadcast
    {
        public $newsItem;
    
        public function __construct(NewsItem $newsItem)
        {
            $this->newsItem = $newsItem;
        }
    
        public function broadcastOn()
        {
            return new Channel('http://example/news-items');
        }
    }
    // Frontend: Listening for events
    var es = new EventSource('http://localhost:3000/.well-known/mercure?topic=' + encodeURIComponent('http://example/news-items'));
    es.addEventListener('message', (messageEvent) => {
        var eventData = JSON.parse(messageEvent.data);
        console.log(eventData);
    });
  2. Secure private channels with JWT and Cookies

    master

    Private channels in Mercure are secured via JWT. To implement this in Laravel, you should create a middleware that generates a mercureAuthorization cookie containing a JWT. This JWT must include a mercure claim with the allowed subscribe topics.

    Important:

    1. Add the mercureAuthorization cookie to the $except array in App\Http\Middleware\EncryptCookies so Laravel does not attempt to decrypt it.
    2. When using EventSource on the frontend, you must set { withCredentials: true } to ensure the cookie is sent with the request.
    // Backend: Middleware to set the authorization cookie
    // Inside your handle method, return a response with the cookie:
    return $response->withCookie($this->createCookie($request->user(), $request->secure()));
    
    // The JWT must contain the 'mercure' claim:
    // 'mercure' => ['subscribe' => ['http://example/user/1/direct-messages']]
    // Frontend: Listening to a private channel
    var es = new EventSource('http://localhost:3000/.well-known/mercure?topic=' + encodeURIComponent('http://example/user/1/direct-messages'), { withCredentials: true });
    es.addEventListener('message', (messageEvent) => {
        var eventData = JSON.parse(messageEvent.data);
        console.log(eventData);
    });
  3. How the MercureBroadcaster sends events

    master

    The MercureBroadcaster implements Laravel's Broadcaster contract to push events to a Mercure hub. When broadcast() is called, it wraps the event name and the data payload into a JSON object with the following structure:

    {
      "event": "event-name",
      "data": { ... payload ... }
    }

    It then publishes an Update to the Mercure hub for each provided channel. The broadcaster determines the privacy of the update based on the channel type:

    • If the channel is an instance of PrivateChannel, the update is marked as private.
    • For other channel types, it uses the channel's name/string representation.
    /* The payload structure sent to the Mercure Hub */
    {
        "event": "YourEventName",
        "data": { "key": "value" }
    }
  4. Configure the Mercure broadcaster

    master

    Update your config/broadcasting.php to include the mercure connection. You must provide the url (the path to the .well-known/mercure endpoint) and a secret used for signing JWTs.

    return [
        'default' => env('BROADCAST_DRIVER', 'mercure'),
    
        'connections' => [
            'mercure' => [
                'driver' => 'mercure',
                'url' => env('MERCURE_URL', 'http://localhost:3000/.well-known/mercure'),
                'secret' => env('MERCURE_SECRET', 'aVerySecretKey'),
            ],
        ],
    ];
  5. Configure the Mercure broadcaster connection

    master

    To use Mercure as a broadcasting driver in Laravel, you must define a mercure connection in your config/broadcasting.php file. The service provider expects a url and a secret key within this connection configuration.

    The secret is used to generate the JWT required by the Mercure Hub for publishing updates. The provider automatically grants the publish: * claim to the generated token.

    // config/broadcasting.php
    
    'connections' => [
        'mercure' => [
            'driver' => 'mercure',
            'url' => 'https://your-mercure-hub-url.com/.well-known/mercure',
            'secret' => env('MERCURE_JWT_SECRET'),
        ],
    ],
  6. Deprecation notice: Use Illuminate Broadcasting channels instead of Duijker\LaravelMercureBroadcaster\Broadcasting\Channel

    master

    The Duijker\LaravelMercureBroadcaster\Broadcasting\Channel class is deprecated. To ensure compatibility and follow Laravel standards, you should migrate to the native Laravel broadcasting classes:

    • For public channels, use Illuminate\Broadcasting\Channel.
    • For private channels, use Illuminate\Broadcasting\PrivateChannel.

    This change is required for versions 3.8.0 and above.