Notifications Usage

cavis edited this page Oct 23, 2015 · 12 revisions

Overview

The notifications system in PMP was designed with PubSubHubbub 0.3 in mind. Some optional functionality defined in the PubSubHubbub spec is not implemented for PMP. However, PMP does implement some functionality that is either loosely defined or not defined at all by PubSubHubbub.

Publishing and notifications are partially compliant with the PubSubHubbub spec. That is, PMP notifications are sent to subscribers according to PubSubHubbub. However, since the publisher and notification hub are both part of the PMP API server, there is no need for the publisher to notify the hub of new content. The PMP API simply checks for new content events and sends the appropriate notifications as needed.

Subscriptions are fully compliant with the PubSubHubbub spec. Any PubSubHubbub compliant subscription client can be used to manage subscriptions to PMP notifications. However, a subscriber must use PMP authentication before any request can be made. A subscriber must also know which topics PMP makes available. And a subscriber must know what content PMP makes available in topic RSS feeds sent via PMP notifications.

The documentation here attempts to explain the key parts of the system and the workflows as they were implemented for PMP, so irrelevant parts of the PubSubHubbub spec are left out.

Topics

A topic is a URI that identifies an RSS 2.0 feed to which can be subscribed. The topic feed is accessible via this URI, and it contains the location of the topic's notification hub via an atom:link with rel="hub" as well as a number of items that represent document events. A subscriber client should use this hub URI to discover the location of the notification hub.

The topics (topic-uri) currently allowed by the PMP API are:

  • https://api.pmp.io/notifications/topics/created - notifies when a new document has been saved to the system
  • https://api.pmp.io/notifications/topics/updated - notifies when an existing document has been saved to the system
  • https://api.pmp.io/notifications/topics/deleted - notifies when a document has been deleted from the system

Topic URIs support only the GET method for HTTP requests. When a GET request is made on a topic URI, the feed that is returned contains the most recent 50 document event items for that topic.

When a topic feed is sent as a notification, it contains only 1 document event item. A document event item does not contain the full content of a document, but only the guid and URI of the document.

Current topic feeds are a "firehose" of documents that you may or may not have access to. You will need to fetch the document itself to determine if you have permission to see it or not. (You'll get a 403 Forbidden if you do not have access to the document).

A topic feed looks like:

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <atom:link rel="hub" href="https://api.pmp.io/notifications" />
        <atom:link rel="self" href="https://api.pmp.io/notifications/topics/updated" type="application/rss+xml" />
        <title>Updated Documents</title>
        <link>https://api.pmp.io/notifications/topics/updated</link>
        <description>Updated Documents</description>
        <item>
            <title>322af975-0c43-4d2d-9936-3cab3680af06</title>
            <link>https://api.pmp.io/docs/322af975-0c43-4d2d-9936-3cab3680af06</link>
            <guid>322af975-0c43-4d2d-9936-3cab3680af06</guid>
            <pubDate>2013-10-22T15:15:37+00:00</pubDate>
        </item>
    </channel>
</rss>

The subscriber callback URI used to receive these notifications will need to be able to process RSS 2.0 feeds.

Hub

The hub is where subscriptions and notifications are managed. The subscriber client should use the hub for all subscription requests. The subscriber callback should be allowed to receive topic feed notifications from the hub.

The notification hub (hub-uri) for the PMP API is:

https://publish.pmp.io/notifications

The notification hub supports only the POST method for HTTP requests. When a POST request is made on the hub URI, the hub determines if the request is to subscribe or unsubscribe and manages the process accordingly.

Internally, the notifications hub periodically checks for new document events. If it finds new events, it then checks if there are any active subscriptions for the new events. If it finds subscriptions for new events, it creates topic feeds for the events and sends them as notifications to the subscriber callbacks.

Callback

The callback is the subscriber-provided service where subscriptions are verified and notifications received. The subscriber callback must be a valid URI, but can be defined by the subscriber. The subscriber callback should use HTTPS if making use of signatures on notifications (more on that later in the outlined workflows).

The subscriber callback must support at least GET and POST method for HTTP requests, according to the outlined workflows below. The callback must receive verification requests via GET, and must receive notifications via POST.

Subscription Workflow

A standard PubSubHubbub subscription client should be able to handle much of the subscription process. The subscription workflow goes like this:

  1. Subscriber client authenticates with the PMP API
  2. Subscriber client auto-discovers the location of the hub from the topic
    1. Request GET {topic-uri} where {topic-uri} is the URI of the desired topic
    2. Extract the value of /rss/channel/atom:link[@rel="hub"]/@href (using XPath syntax)
  3. Subscriber client sends subscription request for the topic to the discovered hub
    1. Request POST {hub-uri} with Content-Type header application/x-www-form-urlencoded and the following parameters:
      • hub.callback (required) the subscriber callback URI that will verify the subscription and receive notifications
      • hub.mode (required) the goal of the request, must be one of the literal strings subscribe or unsubscribe
      • hub.topic (required) the topic URI for the subscription
      • hub.verify (required) the method of verification, must be one of the literal strings sync or async
        • sync indicates that verification must occur before the subscription request's response is returned
        • async indicates that verification can occur after the subscription request's response has returned
      • hub.secret (optional) a subscriber-provided shared secret that will be used to generate an HMAC digest that will be included with notifications
      • hub.verify_token (optional) a subscriber-provided token that will be sent back during verification
    2. If there are problems with the provided fields, HTTP 400 status is returned from the hub to the subscriber client, otherwise verification continues
    3. If hub.verify is async, HTTP 202 status is returned regardless of verification outcome
    4. If hub.verify is sync, then HTTP status returned depends on the outcome of verification and saving of subscription state:
      • If verification and saving of subscription is successful, HTTP 204 status is returned
      • If verification failed, HTTP 412 status is returned
      • If verification is successful but saving of subscription failed, HTTP 500 status is returned
  4. Notification hub sends verification request to the subscriber callback
    1. Request GET {hub.callback} with the following query string parameters:
      • hub.mode (required) the goal of the request, must be one of the literal strings subscribe or unsubscribe
      • hub.topic (required) the topic URI for the subscription
      • hub.challenge (required) a hub-provided challenge code that will be sent back in the response from the subscriber callback
      • hub.verify_token (optional) the subscriber-provided token that was provided in the subscription request
    2. If hub.mode, hub.topic, and hub.verifiy_token match what the subscriber callback expects and the subscriber callback is otherwise satisfied with the verification request, HTTP 200 status is returned from the subscriber callback with the value of hub.challenge in the body of the response
    3. If the subscriber callback is otherwise not satisfied with the verification request, HTTP 404 status is returned from the subscriber callback
  5. Notification hub finishes the subscription request
    1. If the hub.challenge code returned to the hub by the subscriber callback during verification is invalid, verification has failed, and HTTP 412 status is returned by the hub if hub.verify is sync
    2. If the hub.challenge code returned to the hub by the subscriber callback during verification is otherwise acceptable, verification was successful and saving subscription state continues
    3. If the subscription state (subscribe or unsubscribe) cannot be successfully saved, HTTP 500 status is returned by the hub if hub.verify is sync
    4. If the subscription state is successfully saved, HTTP 204 status is returned by the hub if hub.verify is sync
    5. If hub.verify is async, no further communication happens on the original subscription request beyond the HTTP 202 response sent from the hub to the subscriber client

Based on this subscription workflow, the subscriber callback URI must be able to handle GET requests for verification purposes.

Notification Workflow

A standard RSS parser should be able to handle notification feeds. The notification workflow goes like this:

  1. Notification hub creates a topic feed to send as a notification
  2. Notification hub sends the notification to the subscriber callback
    1. Request POST {callback-uri} with the following headers:
      • Content-Type: application/rss+xml
      • X-Hub-Signature: sha1={signature} where {signature} is a 40-byte, hexadecimal HMAC SHA1 signature that uses the subscriber-provided hub.secret as the key. (Said another way, to verify the incoming notification, check the {signature} against a HMAC SHA1 of the XML sent by the request, using the previously-sent hub.secret as a key.)
    2. If the signature is provided and is not acceptable to the subscriber callback, the subscriber callback should ignore the notification
    3. If the signature is provided and is acceptable to the subscriber callback, the subscriber callback should process the feed in the notification accordingly
    4. HTTP 200 status is returned by the subscriber callback regardless of signature

Based on this notification workflow, the subscriber callback URI must also be able to handle POST requests for notification purposes.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.