Skip to content

feat: migrate to the Mercure 1.0 protocol - #8

Open
BySplashGm wants to merge 2 commits into
api-platform:mainfrom
BySplashGm:feat/mercure-1.0
Open

feat: migrate to the Mercure 1.0 protocol#8
BySplashGm wants to merge 2 commits into
api-platform:mainfrom
BySplashGm:feat/mercure-1.0

Conversation

@BySplashGm

@BySplashGm BySplashGm commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Makes this repository work against the Mercure 1.0 protocol.

Hub

caddy:2.8-builder ships Go 1.23.4 and cannot build mercure/caddy@v1.0.0-alpha.3
(requires go >= 1.26), so the builder moves to 2.11.4 — the Caddy version Mercure
pins — and both plugins are now pinned explicitly. Unpinned, xcaddy resolved
mercure/caddy to the latest stable tag and silently gave 0.24.2.

The mercure block is ported directive for directive: flag-form anonymous
(anonymous true is now rejected with unknown mercure directive "true"),
debugger for the renamed ui, and an issuer block replacing the flat
publisher_jwt / subscriber_jwt, which in 1.0 work only under
protocol_version_compatibility. resource_identifier is set deliberately: an
identifier ending in /.well-known/mercure also becomes the base URL that relative
topics resolve against, and the topics here are rel="self" link values.

Client

?topic= is gone; subscriptions are sent as match (exact). match_urlpattern
is not exposed from @api-platform/mercure yet — that's a separate PR, since it's
worth discussing on its own whether that decision belongs in this low-level client.

The resume cursor is also now sent as a last_event_id query parameter, not just
the Last-Event-Id header: every listen() opens a fresh connection, so the id has
to travel with the request, and a native EventSource cannot set headers. The spec
requires the hub to take the union of the query and body components, applying
"alike" to the topic matcher parameters and to last_event_id. The header is still
sent, for implementations that support it.

Tokens

The publisher fixtures are reminted as RFC 9068 access tokens (typ: at+jwt, iss,
aud, exp, authorization_details). The legacy {"mercure": {...}} claim and a
typ of JWT are both rejected in modern mode.

Tests

tests/mercure.spec.ts updated for the new query parameter and token shape.


Verification. Run against a v1.0.0-alpha.3 hub.

@BySplashGm
BySplashGm marked this pull request as ready for review September 4, 2026 13:28
@soyuka

soyuka commented Sep 8, 2026

Copy link
Copy Markdown
Member

can you rebase this one ?

@soyuka

soyuka commented Sep 8, 2026

Copy link
Copy Markdown
Member

Can we split the basic 1.0 compatibility and the new shared-pattern change? I'm not sure we need such behavior in this low-level component.

Test server now runs mercure/caddy v1.0.0-alpha.3. The 2.8 builder ships
Go 1.23.4 and cannot build it (requires go >= 1.26), so the builder moves to
2.11.4 — the Caddy version mercure/caddy pins — and both plugins are pinned
explicitly: unpinned, xcaddy resolved mercure/caddy to the latest stable tag
and silently gave 0.24.2.

Caddyfile ported to modern mode, directive for directive: flag-form
anonymous, `debugger` for the renamed `ui`, and an issuer block replacing the
flat publisher_jwt/subscriber_jwt, which now work only under
protocol_version_compatibility. resource_identifier is set because an
identifier ending in /.well-known/mercure also becomes the base URL relative
topics resolve against, and the topics here are rel="self" link values.

Client subscribes with `match` instead of the removed `topic` parameter. The
tracked topics are those same relative link values, so the exact matcher is
the right semantics; match_urlpattern is not exposed yet.

Publisher fixtures reminted as RFC 9068 access tokens: typ at+jwt, iss, aud,
exp and authorization_details. The legacy `mercure` claim and typ JWT are
both rejected in modern mode.
Every listen() opens a fresh connection, so the id of the last update has to
travel with the request. The client only set the Last-Event-Id header, which
a native EventSource cannot do — resuming worked solely because of the npm
eventsource polyfill, even though the README invites callers to pass their
own EventSource.

The spec is explicit that the hub "MUST then take the union" of the query and
body components and that this "applies to the topic matcher parameters and to
last_event_id ... alike", so the cursor now goes in the query too. The header
is still sent, for implementations that support it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants