Internet DRAFT - draft-dunglas-mercure
draft-dunglas-mercure
Network Working Group K. Dunglas
Internet-Draft Les-Tilleuls.coop
Intended status: Standards Track 8 July 2020
Expires: 9 January 2021
The Mercure Protocol
draft-dunglas-mercure-07
Abstract
Mercure is a protocol enabling the pushing of data updates to web
browsers and other HTTP clients in a fast, reliable and battery-
efficient way. It is especially useful for publishing real-time
updates of resources served through web APIs to web and mobile apps.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 9 January 2021.
Copyright Notice
Copyright (c) 2020 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Simplified BSD License text
as described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Simplified BSD License.
Dunglas Expires 9 January 2021 [Page 1]
Internet-Draft The Mercure Protocol July 2020
Table of Contents
1. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1. Content Negotiation . . . . . . . . . . . . . . . . . . . 5
3. Topic Selectors . . . . . . . . . . . . . . . . . . . . . . . 6
4. Subscription . . . . . . . . . . . . . . . . . . . . . . . . 7
5. Publication . . . . . . . . . . . . . . . . . . . . . . . . . 8
6. Authorization . . . . . . . . . . . . . . . . . . . . . . . . 10
6.1. Publishers . . . . . . . . . . . . . . . . . . . . . . . 11
6.2. Subscribers . . . . . . . . . . . . . . . . . . . . . . . 12
6.3. Payload . . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Reconnection, State Reconciliation and Event Sourcing . . . . 13
8. Active Subscriptions . . . . . . . . . . . . . . . . . . . . 14
8.1. Subscription Events . . . . . . . . . . . . . . . . . . . 15
8.2. Subscription API . . . . . . . . . . . . . . . . . . . . 16
9. JSON-LD Context . . . . . . . . . . . . . . . . . . . . . . . 20
10. Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 20
11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 21
11.1. Well-Known URIs Registry . . . . . . . . . . . . . . . . 21
11.2. Link Relation Types Registry . . . . . . . . . . . . . . 21
11.3. JSON Web Token (JWT) Registry . . . . . . . . . . . . . 21
12. Security Considerations . . . . . . . . . . . . . . . . . . . 22
13. Implementation Status . . . . . . . . . . . . . . . . . . . . 23
13.1. Mercure.rocks Hub . . . . . . . . . . . . . . . . . . . 23
13.2. Ilshidur/node-mercure . . . . . . . . . . . . . . . . . 24
13.3. Symfony . . . . . . . . . . . . . . . . . . . . . . . . 25
13.4. API Platform . . . . . . . . . . . . . . . . . . . . . . 26
13.5. Laravel Mercure Broadcaster . . . . . . . . . . . . . . 26
13.6. dart_mercure . . . . . . . . . . . . . . . . . . . . . . 27
13.7. pymercure . . . . . . . . . . . . . . . . . . . . . . . 28
13.8. Amphp Mercure Publisher . . . . . . . . . . . . . . . . 29
13.9. Java Library for Mercure . . . . . . . . . . . . . . . . 30
13.10. Yii 2 Mercure behavior . . . . . . . . . . . . . . . . . 31
13.11. GitHub Action for Mercure . . . . . . . . . . . . . . . 31
13.12. Other Implementations . . . . . . . . . . . . . . . . . 32
14. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 32
15. Normative References . . . . . . . . . . . . . . . . . . . . 32
16. Informative References . . . . . . . . . . . . . . . . . . . 33
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 35
1. Terminology
The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD,
*SHOULD NOT*, RECOMMENDED, MAY, and OPTIONAL, when they appear in
this document, are to be interpreted as described in [RFC2119].
Dunglas Expires 9 January 2021 [Page 2]
Internet-Draft The Mercure Protocol July 2020
* Topic: The unit to which one can subscribe to changes. The topic
SHOULD be identified by an IRI [RFC3987]. Using an HTTPS
[RFC7230] or HTTP [RFC7230] URI [RFC3986] is RECOMMENDED.
* Update: The message containing the updated version of the topic.
An update can be marked as private, consequently, it must be
dispatched only to subscribers allowed to receive it.
* Topic selector: An expression matching one or several topics.
* Publisher: An owner of a topic. Notifies the hub when the topic
feed has been updated. As in almost all pubsub systems, the
publisher is unaware of the subscribers, if any. Other pubsub
systems might call the publisher the "source". Typically a
website or a web API, but can also be a web browser.
* Subscriber: A client application that subscribes to real-time
updates of topics using topic selectors. Typically a web or a
mobile application, but can also be a server.
* Subscription: A topic selector used by a subscriber to receive
updates. A single subscriber can have several subscriptions, when
it provides several topic selectors.
* Hub: A server that handles subscription requests and distributes
the content to subscribers when the corresponding topics have been
updated. Any hub MAY implement its own policies on who can use
it.
2. Discovery
The discovery mechanism aims at identifying at least 2 URLs.
1. The URL of one or more hubs designated by the publisher.
2. The canonical URL for the topic to which subscribers are expected
to use for subscriptions.
The URL of the hub MUST be the "well-known" [RFC5785] fixed path
"/.well-known/mercure".
If the publisher is a server, it SHOULD advertise the URL of one or
more hubs to the subscriber, allowing it to receive live updates when
topics are updated. If more than one hub URL is specified, the
publisher MUST notifies each hub, so the subscriber MAY subscribe to
one or more of them.
Dunglas Expires 9 January 2021 [Page 3]
Internet-Draft The Mercure Protocol July 2020
Note: Publishers may wish to advertise and publish to more than one
hub for fault tolerance and redundancy. If one hub fails to
propagate an update to the document, then using multiple independent
hub is a way to increase the likelihood of delivery to subscribers.
As such, subscribers may subscribe to one or more of the advertised
hubs.
The publisher SHOULD include at least one Link Header [RFC5988] with
"rel=mercure" (a hub link header). The target URL of these links
MUST be a hub implementing the Mercure protocol.
The publisher MAY provide the following target attributes in the Link
Headers:
* "last-event-id": the identifier of the last event dispatched by
the publisher at the time of the generation of this resource. If
provided, it MUST be passed to the hub through a query parameter
called "Last-Event-ID" and will be used to ensure that possible
updates having been made between the resource generation by the
server and the connection to the hub are not lost. See Section 7.
* "content-type": the content type of the updates that will be
pushed by the hub. If omitted, the subscriber MUST assume that
the content type will be the same as that of the original
resource. Setting the "content-type" attribute is especially
useful to hint that partial updates will be pushed, using formats
such as JSON Patch [RFC6902] or JSON Merge Patch [RFC7386].
* "key-set": the URL of the key set to use to decrypt updates,
encoded in the JWK set format (JSON Web Key Set) [RFC7517]. See
Section 10. As this key set will contain a secret key, the
publisher must ensure that only the subscriber can access to this
URL. To do so, the authorization mechanism (see Section 6) can be
reused.
All these attributes are optional.
The publisher MAY also include one Link Header [RFC5988] with
"rel=self" (the self link header). It SHOULD contain the canonical
URL for the topic to which subscribers are expected to use for
subscriptions. If the Link with "rel=self" is omitted, the current
URL of the resource MUST be used as a fallback.
Minimal example:
Dunglas Expires 9 January 2021 [Page 4]
Internet-Draft The Mercure Protocol July 2020
GET /books/foo HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-type: application/ld+json
Link: <https://example.com/.well-known/mercure>; rel="mercure"
{"@id": "/books/foo", "foo": "bar"}
Links embedded in HTML or XML documents as defined in the WebSub
recommendation [W3C.REC-websub-20180123] MAY also be supported by
subscribers. If both a header and an embedded link are provided, the
header MUST be preferred.
2.1. Content Negotiation
For practical purposes, it is important that the "rel=self" URL only
offers a single representation. As the hub has no way of knowing
what Media Type ([RFC6838]) or language may have been requested by
the subscriber upon discovery, it would not be able to deliver the
content using the appropriate representation of the document.
It is, however, possible to perform content negotiation by returning
an appropriate "rel=self" URL according to the HTTP headers used in
the initial discovery request. For example, a request to "/books/
foo" with an "Accept" header containing "application/ld+json" could
return a "rel=self" value of "/books/foo.jsonld".
The example below illustrates how a topic URL can return different
"Link" headers depending on the "Accept" header that was sent.
GET /books/foo HTTP/1.1
Host: example.com
Accept: application/ld+json
HTTP/1.1 200 OK
Content-type: application/ld+json
Link: </books/foo.jsonld>; rel="self"
Link: <https://example.com/.well-known/mercure>; rel="mercure"
{"@id": "/books/foo", "foo": "bar"}
Dunglas Expires 9 January 2021 [Page 5]
Internet-Draft The Mercure Protocol July 2020
GET /books/foo HTTP/1.1
Host: example.com
Accept: text/html
HTTP/1.1 200 OK
Content-type: text/html
Link: </books/foo.html>; rel="self"
Link: <https://example.com/.well-known/mercure>; rel="mercure"
<!doctype html>
<title>foo: bar</title>
Similarly, the technique can also be used to return a different
"rel=self" URL depending on the language requested by the "Accept-
Language" header.
GET /books/foo HTTP/1.1
Host: example.com
Accept-Language: fr-FR
HTTP/1.1 200 OK
Content-type: application/ld+json
Content-Language: fr-FR
Link: </books/foo-fr-FR.jsonld>; rel="self"
Link: <https://example.com/.well-known/mercure>; rel="mercure"
{"@id": "/books/foo", "foo": "bar", "@context": {"@language": "fr-FR"}}
3. Topic Selectors
A topic selector is an expression intended to be matched by one or
several topics. A topic selector can also be used to match other
topic selectors for authorization purposes. See Section 6.
A topic selector can be any string including URI Templates [RFC6570]
and the reserved string "*" that matches all topics. It is
RECOMMENDED to use URI Templates or the reserved string "*" as topic
selectors.
Note: URLs and IRIs are valid URI templates.
To determine if a string matches a selector, the following steps must
be followed:
1. If the topic selector is "*" then the string matches the
selector.
Dunglas Expires 9 January 2021 [Page 6]
Internet-Draft The Mercure Protocol July 2020
2. If the topic selector and the string are exactly the same, the
string matches the selector. This characteristic allows to
compare a URI Template with another one.
3. If the topic selector is a valid URI Template, and that the
string matches this URI Template, the string matches the
selector.
4. Otherwise the string does not match the selector.
4. Subscription
The subscriber subscribes to a URL exposed by a hub to receive
updates from one or many topics. To subscribe to updates, the client
opens an HTTPS connection following the Server-Sent Events
specification [W3C.REC-eventsource-20150203] to the hub's
subscription URL advertised by the publisher. The "GET" HTTP method
must be used. The connection SHOULD use HTTP version 2 or superior
to leverage multiplexing and other performance-oriented related
features provided by these versions.
The subscriber specifies the list of topics to get updates from by
using one or several query parameters named "topic". The "topic"
query parameters MUST contain topic selectors. See Section 3.
The protocol doesn't specify the maximum number of "topic" parameters
that can be sent, but the hub MAY apply an arbitrary limit. A
subscription is created for every provided "topic" parameter. See
Section 8.1.
The EventSource JavaScript interface
(https://html.spec.whatwg.org/multipage/server-sent-events.html#the-
eventsource-interface) MAY be used to establish the connection. Any
other appropriate mechanism including, but not limited to, readable
streams [W3C.NOTE-streams-api-20161129] and XMLHttpRequest
(https://xhr.spec.whatwg.org/) (used by popular polyfills) MAY also
be used.
The hub sends to the subscriber updates for topics matching the
provided topic selectors.
If an update is marked as "private", the hub MUST NOT dispatch it to
subscribers not authorized to receive it. See Section 6.
The hub MUST send these updates as "text/event-stream" compliant
events [!@W3C.REC-eventsource-20150203].
Dunglas Expires 9 January 2021 [Page 7]
Internet-Draft The Mercure Protocol July 2020
The "data" property MUST contain the new version of the topic. It
can be the full resource, or a partial update by using formats such
as JSON Patch [RFC6902] or JSON Merge Patch [RFC7386].
All other properties defined in the Server-Sent Events specification
MAY be used and MUST be supported by hubs.
The resource SHOULD be represented in a format with hypermedia
capabilities such as JSON-LD [W3C.REC-json-ld-20140116], Atom
[RFC4287], XML [W3C.REC-xml-20081126] or HTML
[W3C.REC-html52-20171214].
Web Linking [RFC5988] SHOULD be used to indicate the IRI of the
resource sent in the event. When using Atom, XML or HTML as the
serialization format for the resource, the document SHOULD contain a
"link" element with a "self" relation containing the IRI of the
resource. When using JSON-LD, the document SHOULD contain an "@id"
property containing the IRI of the resource.
Example:
// The subscriber subscribes to updates
// for the https://example.com/foo topic, the bar topic,
// and to any topic matching https://example.com/books/{name}
const url = new URL('https://example.com/.well-known/mercure');
url.searchParams.append('topic', 'https://example.com/foo');
url.searchParams.append('topic', 'bar');
url.searchParams.append('topic', 'https://example.com/bar/{id}');
const eventSource = new EventSource(url);
// The callback will be called every time an update is published
eventSource.onmessage = function ({data}) {
console.log(data);
};
The hub MAY require subscribers and publishers to be authenticated,
and MAY apply extra authorization rules not defined in this
specification.
5. Publication
The publisher sends updates by issuing "POST" HTTPS requests on the
hub URL. When it receives an update, the hub dispatches it to
subscribers using the established server-sent events connections.
Dunglas Expires 9 January 2021 [Page 8]
Internet-Draft The Mercure Protocol July 2020
The hub MAY also dispatch this update using other protocols such as
WebSub [W3C.REC-websub-20180123] or ActivityPub
[W3C.REC-activitypub-20180123].
An application *CAN* send events directly to subscribers without
using an external hub server, if it is able to do so. In this case,
it *MAY NOT* implement the endpoint to publish updates.
The request MUST be encoded using the "application/x-www-form-
urlencoded" format [W3C.REC-html52-20171214] and contains the
following name-value tuples:
* "topic": The identifiers of the updated topic. It is RECOMMENDED
to use an IRI as identifier. If this name is present several
times, the first occurrence is considered to be the canonical IRI
of the topic, and other ones are considered to be alternate IRIs.
The hub MUST dispatch this update to subscribers that are
subscribed to both canonical or alternate IRIs.
* "data" (optional): the content of the new version of this topic.
* "private" (optional): if this name is set, the update MUST NOT be
dispatched to subscribers not authorized to receive it. See
Section 6. It is recommended to set the value to "on" but it
*CAN* contain any value including an empty string.
* "id" (optional): the topic's revision identifier: it will be used
as the SSE's "id" property. The provided id MUST NOT start with
the "#" character. The provided id SHOULD be a valid IRI. If
omitted, the hub MUST generate a valid IRI [RFC3987]. An UUID
[RFC4122] or a DID (https://www.w3.org/TR/did-core/) MAY be used.
Alternatively the hub MAY generate a relative URI composed of a
fragment (starting with "#"). This is convenient to return an
offset or a sequence that is unique for this hub. Even if
provided, the hub MAY ignore the id provided by the client and
generate its own id.
* "type" (optional): the SSE's "event" property (a specific event
type).
* "retry" (optional): the SSE's "retry" property (the reconnection
time).
In the event of success, the HTTP response's body MUST be the "id"
associated to this update generated by the hub and a success HTTP
status code MUST be returned. The publisher MUST be authorized to
publish updates. See Section 6.
Dunglas Expires 9 January 2021 [Page 9]
Internet-Draft The Mercure Protocol July 2020
Example:
POST /.well-known/mercure HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer [snip]
topic=https://example.com/foo&data=the%20content
HTTP/1.1 200 OK
Content-type: text/plain
urn:uuid:e1ee88e2-532a-4d6f-ba70-f0f8bd584022
6. Authorization
To ensure that they are authorized, both publishers and subscribers
must present a valid JWS [RFC7515] in compact serialization to the
hub. This JWS SHOULD be short-lived, especially if the subscriber is
a web browser. A different key MAY be used to sign subscribers' and
publishers' tokens.
Two mechanisms are defined to present the JWS to the hub:
* using an "Authorization" HTTP header
* using a cookie
If the publisher or the subscriber is not a web browser, it SHOULD
use an "Authorization" HTTP header. This "Authorization" header MUST
contain the string "Bearer" followed by the JWS. The hub will check
that the JWS conforms to the rules (defined later) ensuring that the
client is authorized to publish or subscribe to updates.
By the "EventSource" specification [W3C.REC-eventsource-20150203],
web browsers can not set custom HTTP headers for such connections,
and they can only be established using the "GET" HTTP method.
However, cookies are supported and can be included even in cross-
domain requests if the CORS credentials are set
(https://html.spec.whatwg.org/multipage/server-sent-events.html#dom-
eventsourceinit-withcredentials):
If the publisher or the subscriber is a web browser, it SHOULD send a
cookie called "mercureAuthorization" containing the JWS when
connecting to the hub.
Dunglas Expires 9 January 2021 [Page 10]
Internet-Draft The Mercure Protocol July 2020
Whenever possible, the "mercureAuthorization" cookie SHOULD be set
during discovery (see Section 2) to improve the overall security.
Consequently, if the cookie is set during the discovery, both the
publisher and the hub have to share the same second level domain.
The "Domain" attribute MAY be used to allow the publisher and the hub
to use different subdomains. See Section 2.
The cookie SHOULD have the "Secure", "HttpOnly" and "SameSite"
attributes set. The cookie's "Path" attribute SHOULD also be set to
the hub's URL. See Section 12.
When using authorization mechanisms, the connection MUST use an
encryption layer such as HTTPS.
If both an "Authorization" HTTP header and a cookie named
"mercureAuthorization" are presented by the client, the cookie MUST
be ignored. If the client tries to execute an operation it is not
allowed to, a 403 HTTP status code SHOULD be returned.
6.1. Publishers
Publishers MUST be authorized to dispatch updates to the hub, and
MUST prove that they are authorized to send updates for the specified
topics.
To be allowed to publish an update, the JWS presented by the
publisher MUST contain a claim called "mercure", and this claim MUST
contain a "publish" key. "mercure.publish" contains an array of topic
selectors. See Section 3.
If "mercure.publish":
* is not defined, then the publisher MUST NOT be authorized to
dispatch any update
* contains an empty array, the publisher MUST NOT be authorized to
publish private updates, but can publish public updates for all
topics.
Otherwise, the hub MUST check that every topics of the update to
dispatch matches at least one of the topic selectors contained in
"mercure.publish".
If the publisher is not authorized for all the topics of an update,
the hub MUST NOT dispatch the update (even if some topics in the list
are allowed) and MUST return a 403 HTTP status code.
Dunglas Expires 9 January 2021 [Page 11]
Internet-Draft The Mercure Protocol July 2020
6.2. Subscribers
To receive updates marked as "private", a subscriber MUST prove that
it is authorized for at least one of the topics of this update. If
the subscriber is not authorized to receive an update marked as
"private", it MUST NOT receive it.
To receive updates marked as "private", the JWS presented by the
subscriber MUST have a claim named "mercure" with a key named
"subscribe" that contains an array of topic selectors. See
Section 3.
The hub MUST check that at least one topic of the update to dispatch
(_canonical_ or _alternate_) matches at least one topic selector
provided in "mercure.subscribe".
This behavior makes it possible to subscribe to several topics using
URI templates while guaranteeing that only authorized subscribers
will receive updates marked as private (even if their canonical
topics are matched by these templates).
Let's say that a subscriber wants to receive updates concerning all
_book_ resources it has access to. The subscriber can use the topic
selector "https://example.com/books/{id}" as value of the "topic"
query parameter. Adding this same URI template to the
"mercure.subscribe" claim of the JWS presented by the subscriber to
the hub would allow this subscriber to receive all updates for all
book resources. It is not what we want here: this subscriber is only
authorized to access *some* of these resources.
To solve this problem, the "mercure.subscribe" claim could contain a
topic selector such as: "https://example.com/users/foo/{?topic}".
The publisher could then take advantage of the previously described
behavior by publishing a private update having "https://example.com/
books/1" as canonical topic and "https://example.com/users/
foo/?topic=https%3A%2F%2Fexample.com%2Fbooks%2F1" as alternate topic:
POST /.well-known/mercure HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer [snip]
topic=https://example.com/books/1&topic=https://example.com/users/foo/?topic=https%3A%2F%2Fexample.com%2Fbooks%2F1&private=on
The subscriber is subscribed to "https://example.com/books/{id}" that
is matched by the canonical topic of the update. This canonical
topic isn't matched by the topic selector provided in its JWS claim
Dunglas Expires 9 January 2021 [Page 12]
Internet-Draft The Mercure Protocol July 2020
"mercure.subscribe". However, an alternate topic of the update,
"https://example.com/users/foo/?topic=https%3A%2F%2Fexample.com%2Fa-
random-topic", is matched by it. Consequently, this private update
will be received by this subscriber, while other updates having a
canonical topic matched by the selector provided in a "topic" query
parameter but not matched by selectors in the "mercure.subscribe"
claim will not.
6.3. Payload
The "mercure" claim of the JWS *CAN* also contain user-defined values
under the "payload" key. This JSON document will be attached to the
subscription and made available in subscription events. See
Section 8.1.
For instance, "mercure.payload" can contain the user ID of the
subscriber, a list of groups it belongs to, or its IP address.
Storing data in "mercure.payload" is a convenient way to share data
related to one subscriber to other subscribers.
7. Reconnection, State Reconciliation and Event Sourcing
The protocol allows to reconciliate states after a reconnection. It
can also be used to implement an Event store
(https://en.wikipedia.org/wiki/Event_store).
To allow re-establishment in case of connection lost, events
dispatched by the hub MUST include an "id" property. The value
contained in this "id" property SHOULD be an IRI [RFC3987]. An UUID
[RFC4122] or a DID (https://www.w3.org/TR/did-core/) MAY be used.
According to the server-sent events specification, in case of
connection lost the subscriber will try to automatically re-connect.
During the re-connection, the subscriber MUST send the last received
event id in a Last-Event-ID (https://html.spec.whatwg.org/multipage/
iana.html#last-event-id) HTTP header.
In order to fetch any update dispatched between the initial resource
generation by the publisher and the connection to the hub, the
subscriber MUST send the event id provided during the discovery as a
"Last-Event-ID" header or query parameter. See Section 2.
"EventSource" implementations may not allow to set HTTP headers
during the first connection (before a reconnection) and
implementations in web browsers don't allow to set it.
To work around this problem, the hub MUST also allow to pass the last
event id in a query parameter named "Last-Event-ID".
Dunglas Expires 9 January 2021 [Page 13]
Internet-Draft The Mercure Protocol July 2020
If both the "Last-Event-ID" HTTP header and the query parameter are
present, the HTTP header MUST take precedence.
If the "Last-Event-ID" HTTP header or query parameter exists, the hub
SHOULD send all events published following the one bearing this
identifier to the subscriber.
The reserved value "earliest" can be used to hint the hub to send all
updates it has for the subscribed topics. According to its own
policy, the hub MAY or *MAY NOT* fulfil this request.
The hub MAY discard some events for operational reasons. When the
request contains a "Last-Event-ID" HTTP header or query parameter the
hub MUST set a "Last-Event-ID" header on the HTTP response. The
value of the "Last-Event-ID" response header MUST be the id of the
event preceding the first one sent to the subscriber, or the reserved
value "earliest" if there is no preceding event (it happens when the
hub history is empty, when the subscriber requests the earliest event
or when the subscriber requests an event that doesn't exist).
The subscriber SHOULD NOT assume that no events will be lost (it may
happen, for example if the hub stores only a limited number of events
in its history). In some cases (for instance when sending partial
updates in the JSON Patch [RFC6902] format, or when using the hub as
an event store), updates lost can cause data lost.
To detect if a data lost ocurred, the subscriber *CAN* compare the
value of the "Last-Event-ID" response HTTP header with the "Last-
Event-ID" it requested. In case of data lost, the subscriber SHOULD
re-fetch the original topic.
Note: Native "EventSource" implementations don't give access to
headers associated with the HTTP response, however polyfills and
server-sent events clients in most programming languages allow it.
The hub *CAN* also specify the reconnection time using the "retry"
key, as specified in the server-sent events format.
8. Active Subscriptions
Mercure provides a mechanism to track active subscriptions. If the
hub support this optional set of features, updates will be published
when a subscription is created, or terminated, and a web API exposes
the list of active subscriptions.
Variables are templated and expanded in accordance with [RFC6570].
Dunglas Expires 9 January 2021 [Page 14]
Internet-Draft The Mercure Protocol July 2020
8.1. Subscription Events
If the hub supports the active subscriptions feature, it MUST publish
an update when a subscription is created or terminated. If this
feature is implemented by the hub, an update MUST be dispatched every
time a subscription is created or terminated.
The topic of these updates MUST be an expansion of "/.well-
known/mercure/subscriptions/{topic}/{subscriber}". "{topic}" is the
topic selector used for this subscription and "{subscriber}" is an
unique identifier for the subscriber.
Note: Because it is recommended to use URI Templates and IRIs for the
"{topic}" and "{subscriber}" variables, values will usually contain
the ":", "/", "{" and "}" characters. Per [RFC6570], these
characters are reserved. They MUST be percent encoded during the
expansion process.
If a subscriber has several subscriptions, it SHOULD be identified by
the same identifier. "{subscriber}" SHOULD be an IRI [RFC3987]. An
UUID [RFC4122] or a DID (https://www.w3.org/TR/did-core/) MAY be
used.
The content of the update MUST be a JSON-LD
[W3C.REC-json-ld-20140116] document containing at least the following
properties:
* "@context": the fixed value "https://mercure.rocks/". "@context"
can be omitted if already defined in a parent node. See
Section 9.
* "id": the identifier of this update, it MUST be the same value as
the subscription update's topic
* "type": the fixed value "Subscription"
* "topic": the topic selector used of this subscription
* "subscriber": the topic identifier of the subscriber. It SHOULD
be an IRI.
* "active": "true" when the subscription is active, and "false" when
it is terminated
* "payload" (optional): the content of "mercure.payload" in the
subscriber's JWS (see Section 6)
The JSON-LD document MAY contain other properties.
Dunglas Expires 9 January 2021 [Page 15]
Internet-Draft The Mercure Protocol July 2020
In order to only allow authorized subscribers to receive subscription
events, the subscription update MUST be marked as "private".
Example:
{
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Abb3de268-05b0-4c65-b44e-8f9acefc29d6",
"type": "Subscription",
"topic": "https://example.com/{selector}",
"subscriber": "urn:uuid:bb3de268-05b0-4c65-b44e-8f9acefc29d6",
"active": true,
"payload": {"foo": "bar"}
}
8.2. Subscription API
If the hub supports subscription events (see Section 8.1), it SHOULD
also expose active subscriptions through a web API.
For instance, subscribers interested in maintaining a list of active
subscriptions can call the web API to retrieve them, and then use
subscription events (see Section 8.1) to keep it up to date.
The web API MUST expose endpoints following these patterns:
* "/.well-known/mercure/subscriptions": the collection of
subscriptions
* "/.well-known/mercure/subscriptions/{topic}": the collection of
subscriptions for the given topic selector
* "/.well-known/mercure/subscriptions/{topic}/{subscriber}": a
specific subscription
To access to the URLs exposed by the web API, clients MUST be
authorized according to the rules defined in Section 6. The
requested URL MUST match at least one of the topic selectors provided
in the "mercure.subscribe" key of the JWS.
The web API MUST set the "Content-Type" HTTP header to "application/
ld+json".
URLs returning a single subscription (following the pattern "/.well-
known/mercure/subscriptions/{topic}/{subscriber}") MUST expose the
same JSON-LD document as described in Section 8.1. If the requested
subscription does not exist, a "404" status code MUST be returned.
Dunglas Expires 9 January 2021 [Page 16]
Internet-Draft The Mercure Protocol July 2020
If the requested subscription isn't active anymore, the hub can
either return the JSON-LD document with the "active" property set to
"false" or return a "404" status code. Accordingly, collection
endpoints *CAN* return terminated connections with the "active"
property set to "false" or omit them.
Collection endpoints MUST return JSON-LD documents containing at
least the following properties:
* "@context": the fixed value "https://mercure.rocks/". "@context"
can be omitted if already defined in a parent node. See
Section 9.
* "id": the URL used to retrieve the document
* "type": the fixed value "Subscriptions"
* "subscriptions": an array of subscription documents as described
in Section 8.1
In addition, all endpoints MUST set the "lastEventID" property at the
root of the returned JSON-LD document:
* "lastEventID": the identifier of the last event dispatched by the
hub at the time of this request (see Section 7). The value MUST
be "earliest" if no events have been dispatched yet. The value of
this property SHOULD be passed back to the hub when subscribing to
subscription events to prevent data loss.
As data returned by this web API is volatile, clients SHOULD validate
that a response coming from cache is still valid before using it.
Examples:
Dunglas Expires 9 January 2021 [Page 17]
Internet-Draft The Mercure Protocol July 2020
GET /.well-known/mercure/subscriptions HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-type: application/ld+json
Link: <https://example.com/.well-known/mercure>; rel="mercure"
ETag: urn:uuid:5e94c686-2c0b-4f9b-958c-92ccc3bbb4eb
Cache-control: must-revalidate
{
"@context": "https://mercure.rocks/",
"id": "/.well-known/mercure/subscriptions",
"type": "Subscriptions",
"lastEventID": "urn:uuid:5e94c686-2c0b-4f9b-958c-92ccc3bbb4eb",
"subscriptions": [
{
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Abb3de268-05b0-4c65-b44e-8f9acefc29d6",
"type": "Subscription",
"topic": "https://example.com/{selector}",
"subscriber": "urn:uuid:bb3de268-05b0-4c65-b44e-8f9acefc29d6",
"active": true,
"payload": {"foo": "bar"}
},
{
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2Fa-topic/urn%3Auuid%3A1e0cba4c-4bcd-44f0-ae8a-7b76f7ef1280",
"type": "Subscription",
"topic": "https://example.com/a-topic",
"subscriber": "urn:uuid:1e0cba4c-4bcd-44f0-ae8a-7b76f7ef1280",
"active": true,
"payload": {"baz": "bat"}
},
{
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Aa6c49794-5f74-4723-999c-3a7e33e51d49",
"type": "Subscription",
"topic": "https://example.com/{selector}",
"subscriber": "urn:uuid:a6c49794-5f74-4723-999c-3a7e33e51d49",
"active": true,
"payload": {"foo": "bap"}
}
]
}
Dunglas Expires 9 January 2021 [Page 18]
Internet-Draft The Mercure Protocol July 2020
GET /.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-type: application/ld+json
Link: <https://example.com/.well-known/mercure>; rel="mercure"
ETag: urn:uuid:5e94c686-2c0b-4f9b-958c-92ccc3bbb4eb
Cache-control: must-revalidate
{
"@context": "https://mercure.rocks/",
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D",
"type": "Subscriptions",
"lastEventID": "urn:uuid:5e94c686-2c0b-4f9b-958c-92ccc3bbb4eb",
"subscriptions": [
{
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Abb3de268-05b0-4c65-b44e-8f9acefc29d6",
"type": "Subscription",
"topic": "https://example.com/{selector}",
"subscriber": "urn:uuid:bb3de268-05b0-4c65-b44e-8f9acefc29d6",
"active": true,
"payload": {"foo": "bar"}
},
{
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Aa6c49794-5f74-4723-999c-3a7e33e51d49",
"type": "Subscription",
"topic": "https://example.com/{selector}",
"subscriber": "urn:uuid:a6c49794-5f74-4723-999c-3a7e33e51d49",
"active": true,
"payload": {"foo": "bap"}
}
]
}
Dunglas Expires 9 January 2021 [Page 19]
Internet-Draft The Mercure Protocol July 2020
GET /.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Abb3de268-05b0-4c65-b44e-8f9acefc29d6 HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-type: application/ld+json
Link: <https://example.com/.well-known/mercure>; rel="mercure"
ETag: urn:uuid:5e94c686-2c0b-4f9b-958c-92ccc3bbb4eb
Cache-control: must-revalidate
{
"@context": "https://mercure.rocks/",
"id": "/.well-known/mercure/subscriptions/https%3A%2F%2Fexample.com%2F%7Bselector%7D/urn%3Auuid%3Abb3de268-05b0-4c65-b44e-8f9acefc29d6",
"type": "Subscription",
"topic": "https://example.com/{selector}",
"subscriber": "urn:uuid:bb3de268-05b0-4c65-b44e-8f9acefc29d6",
"active": true,
"payload": {"foo": "bar"},
"lastEventID": "urn:uuid:5e94c686-2c0b-4f9b-958c-92ccc3bbb4eb"
}
9. JSON-LD Context
The JSON-LD context available at "https://mercure.rocks" is the
following:
{
"@context": {
"@vocab": "_:",
"mercure": "https://mercure.rocks/",
"id": "@id",
"type": "@type",
"Subscription": "mercure:Subscription",
"Subscriptions": "mercure:Subscriptions",
"subscriptions": "mercure:subscriptions",
"topic": "mercure:topic",
"subscriber": "mercure:subscriber",
"active": "mercure:active",
"payload": "mercure:payload",
"lastEventID": "mercure:lastEventID"
}
10. Encryption
Using HTTPS does not prevent the hub from accessing the update's
content. Depending of the intended privacy of information contained
in the update, it MAY be necessary to prevent eavesdropping by the
hub.
Dunglas Expires 9 January 2021 [Page 20]
Internet-Draft The Mercure Protocol July 2020
To make sure that the message content can not be read by the hub, the
publisher MAY encrypt the message before sending it to the hub. The
publisher SHOULD use JSON Web Encryption [RFC7516] to encrypt the
update content. The publisher MAY provide the URL pointing to the
relevant encryption key(s) in the "key-set" attribute of the "Link"
HTTP header during the discovery. See Section 2. The "key-set"
attribute MUST link to a key encoded using the JSON Web Key Set
[RFC7517] format. Any other out-of-band mechanism MAY be used
instead to share the key between the publisher and the subscriber.
Update encryption is considered a best practice to prevent mass
surveillance. This is especially relevant if the hub is managed by
an external provider.
11. IANA Considerations
11.1. Well-Known URIs Registry
A new "well-known" URI as described in Section 2 has been registered
in the "Well-Known URIs" registry as described below:
* URI Suffix: mercure
* Change Controller: IETF
* Specification document(s): This specification, Section 2
* Related information: N/A
11.2. Link Relation Types Registry
A new "Link Relation Type" as described in Section 2 has been
registered in the "Link Relation Type" registry with the following
entry:
* Relation Name: mercure
* Description: The Mercure Hub to use to subscribe to updates of
this resource.
* Reference: This specification, Section 2
11.3. JSON Web Token (JWT) Registry
A new "JSON Web Token Claim" as described in Section 6 *will be*
registered in the "JSON Web Token (JWT)" with the following entry:
* Claim Name: mercure
Dunglas Expires 9 January 2021 [Page 21]
Internet-Draft The Mercure Protocol July 2020
* Description: Mercure data.
* Reference: This specification, Section 6
12. Security Considerations
The confidentiality of the secret key(s) used to generate the JWSs is
a primary concern. The secret key(s) MUST be stored securely. They
MUST be revoked immediately in the event of compromission.
Possessing valid JWSs allows any client to subscribe, or to publish
to the hub. Their confidentiality MUST therefore be ensured. To do
so, JWSs MUST only be transmitted over secure connections.
Also, when the client is a web browser, the JWS SHOULD not be made
accessible to JavaScript scripts for resilience against Cross-site
Scripting (XSS) attacks (https://owasp.org/www-community/attacks/
xss/). It's the main reason why, when the client is a web browser,
using "HttpOnly" cookies as the authorization mechanism SHOULD always
be preferred.
In the event of compromission, revoking JWSs before their expiration
is often difficult. To that end, using short-lived tokens is
strongly RECOMMENDED.
The publish endpoint of the hub may be targeted by Cross-Site Request
Forgery (CSRF) attacks (https://owasp.org/www-community/attacks/csrf)
when the cookie-based authorization mechanism is used. Therefore,
implementations supporting this mechanism MUST mitigate such attacks.
The first prevention method to implement is to set the
"mercureAuthorization" cookie's "SameSite" attribute. However, some
web browsers still not support this attribute
(https://caniuse.com/#feat=same-site-cookie-attribute) and will
remain vulnerable. Additionally, hub implementations SHOULD use the
"Origin" and "Referer" HTTP headers set by web browsers to verify
that the source origin matches the target origin. If none of these
headers are available, the hub SHOULD discard the request.
CSRF prevention techniques, including those previously mentioned, are
described in depth in OWASP's Cross-Site Request Forgery (CSRF)
Prevention Cheat Sheet
(https://cheatsheetseries.owasp.org/cheatsheets/Cross-
Site_Request_Forgery_Prevention_Cheat_Sheet.html).
Dunglas Expires 9 January 2021 [Page 22]
Internet-Draft The Mercure Protocol July 2020
13. Implementation Status
[RFC Editor Note: Please remove this entire seciton prior to
publication as an RFC.]
This section records the status of known implementations of the
protocol defined by this specification at the time of posting of this
Internet-Draft, and is based on a proposal described in [RFC6982].
The description of implementations in this section is intended to
assist the IETF in its decision processes in progressing drafts to
RFCs. Please note that the listing of any individual implementation
here does not imply endorsement by the IETF. Furthermore, no effort
has been spent to verify the information presented here that was
supplied by IETF contributors. This is not intended as, and must not
be construed to be, a catalog of available implementations or their
features. Readers are advised to note that other implementations may
exist. According to RFC 6982, "this will allow reviewers and working
groups to assign due consideration to documents that have the benefit
of running code, which may serve as evidence of valuable
experimentation and feedback that have made the implemented protocols
more mature. It is up to the individual working groups to use this
information as they see fit."
13.1. Mercure.rocks Hub
Organization responsible for the implementation:
Dunglas Services SAS Les-Tilleuls.coop
Implementation Name and Details:
Mercure.rocks, available at https://mercure.rocks
(https://mercure.rocks)
Brief Description:
This is the reference implementation of the Mercure hub. It is
written in Go and is optimized for performance.
Level of Maturity:
Widely used.
Coverage:
All the features of the protocol.
Version compatibility:
Dunglas Expires 9 January 2021 [Page 23]
Internet-Draft The Mercure Protocol July 2020
The implementation follows the latest draft.
Licensing:
All code is covered under the GNU Affero Public License version 3 or
later.
Implementation Experience:
Used in production.
Contact Information:
Kévin Dunglas, kevin+mercure@dunglas.fr
(mailto:kevin+mercure@dunglas.fr) https://mercure.rocks
(https://mercure.rocks)
Interoperability:
Reported compatible with all major browsers and server-side tools.
13.2. Ilshidur/node-mercure
Implementation Name and Details:
Ilshidur/node-mercure, https://github.com/Ilshidur/node-mercure
(https://github.com/Ilshidur/node-mercure)
Brief Description:
Hub and Publisher implemented in Node.
Level of Maturity:
Beta, not suitable for production.
Coverage:
All the features of the protocol except the subscription events.
Version compatibility:
The implementation currently follows the revision 5 of the draft.
Licensing:
All code is covered under the GNU Public License version 3 or later.
Dunglas Expires 9 January 2021 [Page 24]
Internet-Draft The Mercure Protocol July 2020
Contact Information:
https://github.com/Ilshidur/node-mercure
(https://github.com/Ilshidur/node-mercure)
Interoperability:
Reported compatible with all major browsers and server-side tools.
13.3. Symfony
Implementation Name and Details:
Symfony Mercure Component, available at
https://symfony.com/doc/current/components/mercure.html
(https://symfony.com/doc/current/components/mercure.html)
Brief Description:
This a publisher library written in PHP. It also provides support
for Mercure in the Symfony web framework.
Level of Maturity:
Widely used.
Coverage:
All the publisher features of the protocol.
Version compatibility:
The implementation follows the latest draft.
Licensing:
All code is covered under the MIT license.
Implementation Experience:
Used in production.
Contact Information:
https://symfony.com (https://symfony.com)
Interoperability:
Dunglas Expires 9 January 2021 [Page 25]
Internet-Draft The Mercure Protocol July 2020
Reported compatible with the Mercure.rocks Hub.
13.4. API Platform
Implementation Name and Details:
API Platform, available at https://api-platform.com/docs/core/
mercure/ (https://api-platform.com/docs/core/mercure/)
Brief Description:
The API Platform framework, allows to create async APIs implementing
the Mercure protocol and to generate clients for these APIs.
Level of Maturity:
Widely used.
Coverage:
All the publisher and consumer features of the protocol.
Version compatibility:
The implementation follows the latest draft.
Licensing:
All code is covered under the MIT license.
Implementation Experience:
Used in production.
Contact Information:
https://api-platform.com (https://api-platform.com)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.5. Laravel Mercure Broadcaster
Implementation Name and Details:
Dunglas Expires 9 January 2021 [Page 26]
Internet-Draft The Mercure Protocol July 2020
Laravel Mercure Broadcaster, available at
https://github.com/mvanduijker/laravel-mercure-broadcaster
(https://github.com/mvanduijker/laravel-mercure-broadcaster)
Brief Description:
Laravel broadcaster for Mercure. Use the Mercure protocol as
transport for Laravel Broadcast.
Level of Maturity:
Production
Coverage:
All the publisher features of the protocol.
Version compatibility:
The implementation currently follows the revision 5 of the draft. An
open Pull Request adds support for the latest version of the draft.
Licensing:
All code is covered under the MIT license.
Implementation Experience:
Used in production.
Contact Information:
https://github.com/mvanduijker/laravel-mercure-broadcaster
(https://github.com/mvanduijker/laravel-mercure-broadcaster)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.6. dart_mercure
Implementation Name and Details:
dart_mercure, available at https://github.com/wallforfry/dart
(https://github.com/wallforfry/dart)_mercure
Brief Description:
Dunglas Expires 9 January 2021 [Page 27]
Internet-Draft The Mercure Protocol July 2020
Publisher and Subscriber library for Dart / Flutter.
Level of Maturity:
Stable
Coverage:
All the publisher and subscriber features of the protocol.
Version compatibility:
The implementation follows the latest draft.
Licensing:
All code is covered under the BSD 2-Clause "Simplified" License.
Contact Information:
https://github.com/wallforfry/dart_mercure
(https://github.com/wallforfry/dart_mercure)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.7. pymercure
Implementation Name and Details:
pymercure, available at https://github.com/vitorluis/python-mercure
(https://github.com/vitorluis/python-mercure)
Brief Description:
Publisher and Subscriber library for Python.
Level of Maturity:
Alpha
Coverage:
All the publisher and subscriber features of the protocol.
Version compatibility:
Dunglas Expires 9 January 2021 [Page 28]
Internet-Draft The Mercure Protocol July 2020
The implementation currently follows the revision 5 of the draft. An
open Pull Request adds support for the latest version of the draft.
Licensing:
All code is covered under the BSD 2-Clause "Simplified" License.
Contact Information:
https://github.com/vitorluis/python-mercure
(https://github.com/vitorluis/python-mercure)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.8. Amphp Mercure Publisher
Implementation Name and Details:
Amphp Mercure Publisher, available at https://github.com/eislambey/
amp-mercure-publisher (https://github.com/eislambey/amp-mercure-
publisher)
Brief Description:
Async Mercure publisher based on Amphp.
Level of Maturity:
Stable
Coverage:
All the publisher features of the protocol.
Version compatibility:
The implementation currently follows the revision 5 of the draft. An
open Pull Request adds support for the latest version of the draft.
Licensing:
All code is covered under the MIT license.
Contact Information:
Dunglas Expires 9 January 2021 [Page 29]
Internet-Draft The Mercure Protocol July 2020
https://github.com/eislambey/amp-mercure-publisher
(https://github.com/eislambey/amp-mercure-publisher)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.9. Java Library for Mercure
Implementation Name and Details:
Java Library for Mercure, available at https://github.com/vitorluis/
java-mercure (https://github.com/vitorluis/java-mercure)
Brief Description:
Java library to publish messages to a Mercure Hub!
Level of Maturity:
Alpha
Coverage:
All the publisher features of the protocol.
Version compatibility:
The implementation currently follows the revision 5 of the draft. An
open Pull Request adds support for the latest version of the draft.
Licensing:
All code is covered under the MIT license.
Contact Information:
https://github.com/vitorluis/java-mercure
(https://github.com/vitorluis/java-mercure)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
Dunglas Expires 9 January 2021 [Page 30]
Internet-Draft The Mercure Protocol July 2020
13.10. Yii 2 Mercure behavior
Implementation Name and Details:
Yii 2 Mercure behavior, available at https://github.com/bizley/
mercure-behavior (https://github.com/bizley/mercure-behavior)
Brief Description:
Yii 2 behavior to automatically publish updates to a Mercure hub.
Level of Maturity:
Stable
Coverage:
All the publisher features of the protocol.
Version compatibility:
The implementation currently follows the revision 5 of the draft.
Licensing:
All code is covered under the Apache License 2.0.
Contact Information:
https://github.com/bizley/mercure-behavior
(https://github.com/bizley/mercure-behavior)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.11. GitHub Action for Mercure
Implementation Name and Details:
GitHub Action for Mercure, available at
https://github.com/marketplace/actions/github-action-for-mercure
(https://github.com/marketplace/actions/github-action-for-mercure)
Brief Description:
Send a Mercure update when a GitHub event occurs.
Dunglas Expires 9 January 2021 [Page 31]
Internet-Draft The Mercure Protocol July 2020
Level of Maturity:
Stable
Coverage:
All the publisher features of the protocol.
Version compatibility:
The implementation currently follows the latest version of the draft.
Licensing:
All code is covered under the GNU Public License version 3 or later.
Contact Information:
https://github.com/Ilshidur/action-mercure
(https://github.com/Ilshidur/action-mercure)
Interoperability:
Reported compatible with the reference implementation of the Mercure
Hub.
13.12. Other Implementations
Other implementations can be found on GitHub:
https://github.com/topics/mercure (https://github.com/topics/mercure)
14. Acknowledgements
Parts of this specification, especially Section 2 have been adapted
from the WebSub recommendation [W3C.REC-websub-20180123]. The editor
wish to thanks all the authors of this specification.
15. Normative References
[RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517,
DOI 10.17487/RFC7517, May 2015,
<https://www.rfc-editor.org/info/rfc7517>.
[RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web
Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May
2015, <https://www.rfc-editor.org/info/rfc7515>.
Dunglas Expires 9 January 2021 [Page 32]
Internet-Draft The Mercure Protocol July 2020
[RFC3987] Duerst, M. and M. Suignard, "Internationalized Resource
Identifiers (IRIs)", RFC 3987, DOI 10.17487/RFC3987,
January 2005, <https://www.rfc-editor.org/info/rfc3987>.
[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
Protocol (HTTP/1.1): Message Syntax and Routing",
RFC 7230, DOI 10.17487/RFC7230, June 2014,
<https://www.rfc-editor.org/info/rfc7230>.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66,
RFC 3986, DOI 10.17487/RFC3986, January 2005,
<https://www.rfc-editor.org/info/rfc3986>.
[RFC5785] Nottingham, M. and E. Hammer-Lahav, "Defining Well-Known
Uniform Resource Identifiers (URIs)", RFC 5785,
DOI 10.17487/RFC5785, April 2010,
<https://www.rfc-editor.org/info/rfc5785>.
[W3C.REC-json-ld-20140116]
Sporny, M., Kellogg, G., and M. Lanthaler, "JSON-LD 1.0",
World Wide Web Consortium Recommendation REC-json-ld-
20140116, 16 January 2014,
<http://www.w3.org/TR/2014/REC-json-ld-20140116>.
[RFC7516] Jones, M. and J. Hildebrand, "JSON Web Encryption (JWE)",
RFC 7516, DOI 10.17487/RFC7516, May 2015,
<https://www.rfc-editor.org/info/rfc7516>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.,
and D. Orchard, "URI Template", RFC 6570,
DOI 10.17487/RFC6570, March 2012,
<https://www.rfc-editor.org/info/rfc6570>.
[RFC5988] Nottingham, M., "Web Linking", RFC 5988,
DOI 10.17487/RFC5988, October 2010,
<https://www.rfc-editor.org/info/rfc5988>.
16. Informative References
Dunglas Expires 9 January 2021 [Page 33]
Internet-Draft The Mercure Protocol July 2020
[W3C.REC-eventsource-20150203]
Hickson, I., "Server-Sent Events", World Wide Web
Consortium Recommendation REC-eventsource-20150203, 3
February 2015,
<http://www.w3.org/TR/2015/REC-eventsource-20150203>.
[W3C.NOTE-streams-api-20161129]
Moussa, F. and T. Yoshino, "Streams API", World Wide Web
Consortium NOTE NOTE-streams-api-20161129, 29 November
2016,
<https://www.w3.org/TR/2016/NOTE-streams-api-20161129>.
[RFC4287] Nottingham, M., Ed. and R. Sayre, Ed., "The Atom
Syndication Format", RFC 4287, DOI 10.17487/RFC4287,
December 2005, <https://www.rfc-editor.org/info/rfc4287>.
[RFC7386] Hoffman, P. and J. Snell, "JSON Merge Patch", RFC 7386,
DOI 10.17487/RFC7386, October 2014,
<https://www.rfc-editor.org/info/rfc7386>.
[W3C.REC-websub-20180123]
Genestoux, J. and A. Parecki, "WebSub", World Wide Web
Consortium Recommendation REC-websub-20180123, 23 January
2018, <https://www.w3.org/TR/2018/REC-websub-20180123>.
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
Specifications and Registration Procedures", BCP 13,
RFC 6838, DOI 10.17487/RFC6838, January 2013,
<https://www.rfc-editor.org/info/rfc6838>.
[W3C.REC-xml-20081126]
Bray, T., Paoli, J., Sperberg-McQueen, M., Maler, E., and
F. Yergeau, "Extensible Markup Language (XML) 1.0 (Fifth
Edition)", World Wide Web Consortium Recommendation REC-
xml-20081126, 26 November 2008,
<http://www.w3.org/TR/2008/REC-xml-20081126>.
[W3C.REC-html52-20171214]
Faulkner, S., Eicholz, A., Leithead, T., Danilo, A., and
S. Moon, "HTML 5.2", World Wide Web Consortium
Recommendation REC-html52-20171214, 14 December 2017,
<https://www.w3.org/TR/2017/REC-html52-20171214>.
[W3C.REC-activitypub-20180123]
Webber, C. and J. Tallon, "ActivityPub", World Wide Web
Consortium Recommendation REC-activitypub-20180123, 23
January 2018,
<https://www.w3.org/TR/2018/REC-activitypub-20180123>.
Dunglas Expires 9 January 2021 [Page 34]
Internet-Draft The Mercure Protocol July 2020
[RFC6982] Sheffer, Y. and A. Farrel, "Improving Awareness of Running
Code: The Implementation Status Section", RFC 6982,
DOI 10.17487/RFC6982, July 2013,
<https://www.rfc-editor.org/info/rfc6982>.
[RFC6902] Bryan, P., Ed. and M. Nottingham, Ed., "JavaScript Object
Notation (JSON) Patch", RFC 6902, DOI 10.17487/RFC6902,
April 2013, <https://www.rfc-editor.org/info/rfc6902>.
[RFC4122] Leach, P., Mealling, M., and R. Salz, "A Universally
Unique IDentifier (UUID) URN Namespace", RFC 4122,
DOI 10.17487/RFC4122, July 2005,
<https://www.rfc-editor.org/info/rfc4122>.
Author's Address
Kevin Dunglas
Les-Tilleuls.coop
82 rue Winston Churchill
59160 Lille
France
Email: kevin@les-tilleuls.coop
Dunglas Expires 9 January 2021 [Page 35]