PHPackages                             bentools/mercure-php-hub - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. bentools/mercure-php-hub

Abandoned → [freddie/mercure-x](/?search=freddie%2Fmercure-x)ArchivedProject[HTTP &amp; Networking](/categories/http)

bentools/mercure-php-hub
========================

A PHP Implementation of the Mercure Hub protocol.

0.1(5y ago)21351[2 PRs](https://github.com/bpolaszek/mercure-php-hub/pulls)GPL-3.0-onlyPHPPHP &gt;=7.4

Since Jun 17Pushed 4y ago1 watchersCompare

[ Source](https://github.com/bpolaszek/mercure-php-hub)[ Packagist](https://packagist.org/packages/bentools/mercure-php-hub)[ RSS](/packages/bentools-mercure-php-hub/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (1)Dependencies (30)Versions (4)Used By (0)

[![CI Workflow](https://github.com/bpolaszek/mercure-php-hub/workflows/CI%20Workflow/badge.svg)](https://github.com/bpolaszek/mercure-php-hub/workflows/CI%20Workflow/badge.svg)[![codecov](https://camo.githubusercontent.com/2a7cb0297389f85ab20c78e7a09d9e6ff71d409d58f9f1fba6b2f52aec64e8c7/68747470733a2f2f636f6465636f762e696f2f67682f62706f6c61737a656b2f6d6572637572652d7068702d6875622f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/bpolaszek/mercure-php-hub)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/37a8818b493719da4f8a8e516e78d0411587a316d6c92724a6309d7d340b7885/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f62706f6c61737a656b2f6d6572637572652d7068702d6875622f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/bpolaszek/mercure-php-hub/?branch=master)

Mercure PHP Hub
===============

[](#mercure-php-hub)

This POC was a PHP implementation of the [Mercure Hub Specification](https://mercure.rocks/spec).

This repository will no longer be maintained, as I recently released [Freddie](https://github.com/bpolaszek/freddie), which is a brand new implementation leveraging [Framework X](https://framework-x.org/) (still using ReactPHP under the hood).

Installation
------------

[](#installation)

PHP 7.4+ (and Redis, or a Redis instance, if using the Redis transport) is required to run the hub.

```
composer create-project bentools/mercure-php-hub:dev-master
```

Usage
-----

[](#usage)

```
./bin/mercure --jwt-key=\!ChangeMe\!
```

You can use environment variables (UPPER\_SNAKE\_CASE) to replace CLI options for better convenience. The hub will also check for the presence of a `/etc/mercure/mercure.env` file, then make use of the [Symfony DotEnv](https://github.com/symfony/dotenv) component to populate variables.

Check out [configuration.php](src/Configuration/Configuration.php#L20) for full configuration options.

Advantages and limitations
--------------------------

[](#advantages-and-limitations)

This implementation does not provide SSL nor HTTP2 termination, so you'd better put a reverse proxy in front of it.

Example with nginx:

```
upstream mercure {
    server 127.0.0.1:3000;
}

server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/ssl/certs/example.com/example.com.cert;
    ssl_certificate_key /etc/ssl/certs/example.com/example.com.key;
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

    location /.well-known/mercure {
        proxy_pass http://mercure;
        proxy_read_timeout 24h;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

By default, the hub will run as a simple event-dispatcher. It can fit common needs for a basic usage, but is not scalable (opening another process won't share the same event emitter).

On the other hand, you can launch the hub on **multiple ports** and/or **multiple servers** with a Redis transport (as soon as they share the same Redis instance) and leverage a load-balancer to distribute the traffic. This is currently not possible with the open-source Go implementation of the hub because of concurrency restrictions on the *bolt* transport.

```
upstream mercure {
    # 4 instances on 10.1.2.3
    server 10.1.2.3:3000;
    server 10.1.2.3:3001;
    server 10.1.2.3:3002;
    server 10.1.2.3:3003;

    # 4 instances on 10.1.2.4
    server 10.1.2.4:3000;
    server 10.1.2.4:3001;
    server 10.1.2.4:3002;
    server 10.1.2.4:3003;
}
```

```
./bin/mercure --transport-url="redis://localhost" --jwt-key=\!ChangeMe\!
```

### Benchmarks

[](#benchmarks)

Simulated 1 / 100 /1000 subscribers on server A, 1 publisher blasting messages on server B, Hub on server C (and D for the latter).

ImplementationTransportServersNodes1 subscriber100 subscribers1000 subscribersMercure.rocks GO HubBolt11361 / 286129 / 4989142 / 682ReactPHP implementationPHP11860 / 295519 / 452645 / 322ReactPHP implementationRedis (local)111548 / 411393 / 5861112 / 777ReactPHP implementationRedis (local)14108 / 7661 / 285261 / 688ReactPHP implementationRedis (shared)283035 / 1441183 / 7864708 / 2698Units are `POSTs (publish) / s` / `Received events / s` (total for all subscribers).

Nodes are the total number of ReactPHP open ports.

Hub was hosted on cheap server(s): 2GB / 2 CPU VPS (Ubuntu 20.04). You could probably reach a very high level of performance with better-sized servers and dedicated CPUs.

Feature coverage
----------------

[](#feature-coverage)

FeatureCoveredJWT through `Authorization` header✅JWT through `mercureAuthorization` Cookie✅Different JWTs for subscribers / publishers✅Allow anonymous subscribers✅CORS✅Private updates✅URI Templates for topics✅Health check endpoint✅HMAC SHA256 JWT signatures✅RS512 JWT signatures✅Environment variables configuration✅Custom message IDs✅Last event ID✅️ (except: `earliest` on REDIS transport)Customizable event type✅️Customizable `retry` directive✅️Logging❌ (WIP)️Metrics❌ (WIP)️Subscription events❌️Subscription API❌️Configuration w/ config file❌️Payload❌️Heartbeat❌️`Forwarded` / `X-Forwarded-For` headers❌️Alternate topics❌️Additional features
-------------------

[](#additional-features)

This implementation provides features which are not defined in the original specification.

### Subscribe / Publish topic exclusions

[](#subscribe--publish-topic-exclusions)

Mercure leverages [URI Templates](https://tools.ietf.org/html/rfc6570) to grant subscribe and/or publish auhorizations on an URI pattern basis:

```
{
  "mercure": {
    "publish": [
      "https://example.com/items/{id}"
    ],
    "subscribe": [
      "https://example.com/items/{id}"
    ]
  }
}
```

However, denying access to a specific URL matching an URI template requires you to explicitely list authorized items:

```
{
  "mercure": {
    "publish": [
      "https://example.com/items/1",
      "https://example.com/items/2",
      "https://example.com/items/4"
    ],
    "subscribe": [
      "https://example.com/items/1",
      "https://example.com/items/2",
      "https://example.com/items/4"
    ]
  }
}
```

When dealing with thousands of possibilities, it can quicky become a problem. The Mercure PHP Hub allows you to specify denylists through the `publish_exclude` and `subscribe_exclude` keys, which accept any topic selector:

```
{
  "mercure": {
    "publish": [
      "https://example.com/items/{id}"
    ],
    "publish_exclude": [
      "https://example.com/items/3"
    ],
    "subscribe": [
      "https://example.com/items/{id}"
    ],
    "subscribe_exclude": [
      "https://example.com/items/3"
    ]
  }
}
```

### Json Web Token Generator

[](#json-web-token-generator)

You can generate a JWT to use on the hub from the command-line:

```
./bin/mercure jwt:generate
```

It will ask you interactively what topic selectors you want to allow/deny for publishing/subscribing, and ask you for an optional TTL.

If you want a raw output (to pipe the generated JWT for instance), use the `--raw` option.

To disable interaction, you can use the following example:

```
./bin/mercure jwt:generate --no-interactive --publish=/foo/{id} --publish=/bar --publish-exclude=/foo/bar
```

It will use your JWT keys environment variables, or you can use the `--jwt-key`, `--publisher-jwt-key`, `--subscriber-jwt-key` options.

For a full list of available options, run this:

```
./bin/mercure jwt:generate -h
```

Tests
-----

[](#tests)

This project is covered with [Pest](https://pestphp.com/) tests. Coverage has to be improved: feel free to contribute.

```
composer tests:run
```

Contribute
----------

[](#contribute)

If you want to improve this project, feel free to submit PRs:

- CI will yell if you don't follow [PSR-12 coding standards](https://www.php-fig.org/psr/psr-12/)
- In the case of a new feature, it must come along with tests
- [PHPStan](https://phpstan.org/) analysis must pass at level 5

You can run `composer ci:check` before committing to ensure all CI requirements are successfully met.

License
-------

[](#license)

GNU General Public License v3.0.

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity16

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

1961d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/acdd1a8ee0e657ddd06cf11f98a32100ef7121afb8aa270a5b295f5c29c038b3?d=identicon)[bpolaszek](/maintainers/bpolaszek)

---

Top Contributors

[![bpolaszek](https://avatars.githubusercontent.com/u/5569077?v=4)](https://github.com/bpolaszek "bpolaszek (30 commits)")

---

Tags

hubmercurephppublishpubsubsubscribehttpasyncreactphpssemercurepublishsubscribepubsubserver sent events

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/bentools-mercure-php-hub/health.svg)

```
[![Health](https://phpackages.com/badges/bentools-mercure-php-hub/health.svg)](https://phpackages.com/packages/bentools-mercure-php-hub)
```

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[kimai/kimai

Kimai - Time Tracking

4.6k7.4k1](/packages/kimai-kimai)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
