├── CODE_OF_CONDUCT.md ├── PATCHES.html ├── README.md ├── errata └── README.md ├── implementation-reports ├── HUB-TEMPLATE.md ├── HUB-ballerina.md ├── HUB-dobrado.md ├── HUB-flask-websub.md ├── HUB-mastodon.md ├── HUB-promulgate.md ├── HUB-pubsubhubbub-appspot-com.md ├── HUB-switchboard.md ├── HUB-twitch.md ├── HUB-websub-superfeedr-com.md ├── HUB-websubhub.md ├── HUB-webubbub.md ├── HUB-wso2-apim.md ├── PUBLISHER-TEMPLATE.md ├── PUBLISHER-ballerina.md ├── PUBLISHER-diaspora.md ├── PUBLISHER-dobrado.md ├── PUBLISHER-falcon.md ├── PUBLISHER-flask-websub.md ├── PUBLISHER-mastodon.md ├── PUBLISHER-wordpress-pubsubhubbub.md ├── README.md ├── SUBSCRIBER-TEMPLATE.md ├── SUBSCRIBER-ballerina.md ├── SUBSCRIBER-dobrado.md ├── SUBSCRIBER-feedmail.md ├── SUBSCRIBER-flask-websub.md ├── SUBSCRIBER-mastodon.md └── SUBSCRIBER-superfeedr.com.md ├── index.html ├── source.html ├── staged ├── cr.html ├── fpwd.html ├── pr.html ├── rec │ ├── index.html │ ├── manifest.txt │ └── websub-overview.svg └── wd.html └── w3c.json /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /PATCHES.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Corrections, Modifications, and Patches 6 | 7 | 8 | 9 |

Corrections, Modifications, Patches, Contributions

10 | 11 |

Corrections, modifications, patches, contributions and the like 12 | from entities other than W3C-Members 13 | will not be incorporated into the W3C software distributions, 14 | documents or other publications unless accompanied by the 15 | following statement on behalf of the person submitted the 16 | materials ("The Contributor"):

17 | 18 |

W3C ( 19 | MIT, 20 | 22 | ERCIM, Keio) is 23 | hereby permitted to distribute these materials under W3C Software 24 | and Document 25 | licenses.

26 | 27 |

Furthermore:

28 | 29 |
    30 |
  1. The Contributor vouches that she has all rights necessary to 31 | contribute the materials in a way that does not violate copyright, 32 | patent, and trademark rights; contractual obligations, or libel and 33 | export control regulations.
  2. 34 | 35 |
  3. The Contributor agrees that all contributed materials will be 36 | governed by the W3C Software 37 | or Document 38 | licenses.
  4. 39 | 40 |
  5. W3C will retain attribution of authorship. The W3C makes no 41 | a-priori commitment to support contributions.
  6. 42 |
43 | 44 |

I the undersigned represent that I either own the copyright, or 45 | have the authority to grant these rights:

46 | 47 |
Name,Company      ___________________________________
48 | 
49 | Title             ___________________________________
50 | 
51 | Software          ___________________________________
52 | /Document
53 | 
54 | Signature         ___________________________________
55 | 
56 | Date              ___________________________________
57 | 
58 | 59 |

Please print, sign and send by postal mail to the following 60 | address:

61 | 62 |
        World-Wide Web Consortium
63 |         MIT Computer Science and Artificial Intelligence Laboratory (CSAIL)
64 |         The Stata Center, Building 32 - 32 Vassar Street
65 |         Cambridge, MA 02139
66 |         USA
67 | 
68 | 69 |

You might also send a signed email containing the 70 | filled form or the required information to an archived W3C 71 | mailing-list.

72 | 73 |

Also, please send an email to the project/CVS-repository owner 74 | and site-policy@w3.org with 75 | an expression of the same.

76 | 77 |
78 |
site-policy@w3.org 79 | (rigo@w3.org) March 2004
80 |

Last update $Date: 2004/03/30 18:13:31 $ by $Author: rigo $

81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebSub 2 | 3 | The WebSub Recommendation was produced by the W3C Social Web Working Group. 4 | 5 | REC: https://www.w3.org/TR/2018/REC-websub-20180123/ 6 | 7 | Editor's Draft: https://w3c.github.io/websub/ 8 | 9 | ## Background: 10 | * The current spec was imported from https://github.com/pubsubhubbub/pubsubhubbub 11 | * The working group [resolved on 2016-09-23](https://www.w3.org/wiki/Socialwg/2016-09-23-minutes#Pubsubhubbub) to publish the Editor's Draft as a First Public Working Draft (FPWD) with the name "PubSub" (shortname: "pubsub") 12 | * The working group [resolved on 2016-11-18](https://www.w3.org/wiki/Socialwg/2016-11-18-minutes#PubSub_renaming) to rename the spec to "WebSub" with a shortname of "websub". 13 | 14 | ## Pull requests 15 | 16 | Please make sure you commit changes to `source.html`. The content of `index.html` is regenerated from `source.html`. 17 | -------------------------------------------------------------------------------- /errata/README.md: -------------------------------------------------------------------------------- 1 | WebSub Errata 2 | ============= 3 | 4 | No errata have been reported yet. 5 | 6 | -------------------------------------------------------------------------------- /implementation-reports/HUB-TEMPLATE.md: -------------------------------------------------------------------------------- 1 | This file is a template implementation report for WebSub subscribers. Copy this file to a new .md file and change the name to `HUB-project-name.md`, your project name (lowercase with hyphens between words). Fill out the information based on the details of your implementation. It's okay to not check all the boxes, we are more interested in knowing how much of the spec is implemented than getting everyone to tick every box. When you are finished, submit a pull request or link to your file in a [new issue](https://github.com/w3c/websub/issues). 2 | 3 | For items that have a number next to the checkbox, the number corresponds with the test number on websub.rocks. You can use that tool to check whether you support the feature properly. To mark a statement as true, add an x between the brackets, e.g. [x]. If the statement does not apply to your implementation, use [na] and add a sentence explaining why it does not apply. 4 | 5 | Delete the section above when filling out your copy of this file. 6 | 7 | # Implementation Name (Replace this header) 8 | 9 | Implementation Home Page URL: 10 | 11 | Source code repo URL(s) (optional): 12 | * [ ] 100% open source implementation 13 | 14 | Programming Language(s): 15 | 16 | Developer(s): [Name](https://you.example.com) 17 | 18 | Answers are: 19 | * [ ] Confirmed via websub.rocks (for applicable results) 20 | * [ ] All results are self-reported 21 | 22 | ## Subscription 23 | 24 | * [ ] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 25 | * [ ] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 26 | * [ ] 102: Ignores unrecognized parameters in the subscription request 27 | * [ ] 103: Allows subscribers to re-request active subscriptions before they expire 28 | * [ ] 104: Supports unsubscription requests 29 | * [ ] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 30 | * [ ] Allows subscribers to request a specific lease duration 31 | * If not, then describe the default lease duration issued, or other specifics here 32 | 33 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 34 | 35 | ## Distribution 36 | 37 | * [ ] 100: Sends a notification with a matching content-type of the topic URL 38 | * [ ] 100: Sends a notification with the full contents of the topic 39 | * [ ] 101: Sends a notification with a valid signature 40 | * Please select the signature method(s) that the hub uses to sign requests 41 | * [ ] sha1 42 | * [ ] sha256 43 | * [ ] sha384 44 | * [ ] sha512 45 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 46 | 47 | -------------------------------------------------------------------------------- /implementation-reports/HUB-ballerina.md: -------------------------------------------------------------------------------- 1 | # Ballerina 2 | 3 | Implementation Home Page URL: [ballerina/websub](https://central.ballerina.io/ballerina/websubhub/latest) 4 | 5 | Source code repo URL(s) (optional): https://github.com/ballerina-lang/ballerina 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ballerina 9 | 10 | Developer(s): [Ballerina](https://ballerina.io/) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * Self-reported with JSON content 21 | * [x] 102: Ignores unrecognized parameters in the subscription request 22 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 23 | * [x] 104: Supports unsubscription requests 24 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 25 | * [x] Allows subscribers to request a specific lease duration 26 | * If not, then describe the default lease duration issued, or other specifics here 27 | 28 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 29 | 30 | ## Distribution 31 | 32 | * [x] 100: Sends a notification with a matching content-type of the topic URL 33 | * publisher defines content to deliver 34 | * [x] 100: Sends a notification with the full contents of the topic 35 | * [x] 101: Sends a notification with a valid signature 36 | * Please select the signature method(s) that the hub uses to sign requests 37 | * [x] sha1 38 | * [x] sha256 39 | * [x] sha384 40 | * [x] sha512 41 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 42 | 43 | -------------------------------------------------------------------------------- /implementation-reports/HUB-dobrado.md: -------------------------------------------------------------------------------- 1 | # Dobrado 2 | 3 | Implementation Home Page URL: https://dobrado.net 4 | 5 | Source code repo URL(s) (optional): https://gitlab.com/dobrado/dobrado 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): PHP 9 | 10 | Developer(s): [Malcolm Blaney](https://unicyclic.com/mal) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [ ] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [ ] 104: Supports unsubscription requests 23 | * [ ] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [x] Allows subscribers to request a specific lease duration 25 | * If not, then describe the default lease duration issued, or other specifics here 26 | 27 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 28 | 29 | ## Distribution 30 | 31 | * [x] 100: Sends a notification with a matching content-type of the topic URL 32 | * [x] 100: Sends a notification with the full contents of the topic 33 | * [ ] 101: Sends a notification with a valid signature 34 | * Please select the signature method(s) that the hub uses to sign requests 35 | * [ ] sha1 36 | * [ ] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 40 | 41 | -------------------------------------------------------------------------------- /implementation-reports/HUB-flask-websub.md: -------------------------------------------------------------------------------- 1 | # Flask-WebSub 2 | 3 | An implementation of a WebSub hub, publisher and subscriber as a Flask 4 | extension. The implementation is meant to be used as a library that can be 5 | integrated in a larger application. 6 | 7 | Implementation Home Page URL: https://github.com/marten-de-vries/Flask-WebSub 8 | 9 | Source code repo URL(s): https://github.com/marten-de-vries/Flask-WebSub 10 | * [x] 100% open source implementation 11 | 12 | Programming Language(s): Python 3 (with the Flask, Celery and requests 13 | libraries) 14 | 15 | Developer(s): [Marten de Vries](https://ma.rtendevri.es) 16 | 17 | Answers are: 18 | * [x] Confirmed via websub.rocks (for applicable results) 19 | * [ ] All results are self-reported 20 | 21 | ## Subscription 22 | 23 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 24 | * [na] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 25 | I implemented this, but I did not test it with HTTPS enabled yet, so the test 26 | does not actually send the secret. 27 | * [x] 102: Ignores unrecognized parameters in the subscription request 28 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 29 | * [x] 104: Supports unsubscription requests 30 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 31 | * [x] Allows subscribers to request a specific lease duration 32 | * within configurable limits, at least. If the subscriber does not specify a 33 | lease duration, a configurable default is used. If the library user 34 | specifies nothing, the defaults are: 35 | - min: a minute 36 | - default: 10 days 37 | - max: 31 days 38 | 39 | ## Distribution 40 | 41 | * [x] 100: Sends a notification with a matching content-type of the topic URL 42 | * [x] 100: Sends a notification with the full contents of the topic 43 | * [x] 101: Sends a notification with a valid signature 44 | * Please select the signature method(s) that the hub uses to sign requests 45 | * [x] sha1 46 | * [x] sha256 47 | * [x] sha384 48 | * [x] sha512 (This is the default. It's configurable.) 49 | * [na] Sends only a diff of the topic URL for Atom or RSS feeds 50 | No, but the library does allow you to set the body to sent yourself. So a 51 | user could make it return a diff. 52 | -------------------------------------------------------------------------------- /implementation-reports/HUB-mastodon.md: -------------------------------------------------------------------------------- 1 | # Mastodon 2 | 3 | Implementation Home Page URL: https://mastodon.social/ 4 | 5 | Source code repo URL(s) (optional): 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ruby 9 | 10 | Developer(s): [Eugen Rochko](https://github.com/Gargron) 11 | 12 | Answers are: 13 | * [ ] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | Note: Answers were reported in IRC by Eugen Rochko and transcribed to this report by Aaron Parecki. https://chat.indieweb.org/social/2017-07-12#t1499876947598000 17 | 18 | ## Subscription 19 | 20 | * [ ] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 21 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 22 | * [x] 102: Ignores unrecognized parameters in the subscription request 23 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 24 | * [x] 104: Supports unsubscription requests 25 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 26 | * [x] Allows subscribers to request a specific lease duration 27 | * A min/max range is enforced 28 | 29 | ## Distribution 30 | 31 | * [x] 100: Sends a notification with a matching content-type of the topic URL 32 | * [ ] 100: Sends a notification with the full contents of the topic 33 | * [ ] 101: Sends a notification with a valid signature 34 | * Please select the signature method(s) that the hub uses to sign requests 35 | * [x] sha1 36 | * [ ] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [x] Sends only a diff of the topic URL for Atom or RSS feeds 40 | 41 | -------------------------------------------------------------------------------- /implementation-reports/HUB-promulgate.md: -------------------------------------------------------------------------------- 1 | # Promulgate 2 | 3 | Implementation Home Page URL: https://github.com/barryf/promulgate 4 | 5 | Source code repo URL(s) (optional): https://github.com/barryf/promulgate 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ruby 9 | 10 | Developer(s): [Barry Frost](https://barryfrost.com) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [x] 104: Supports unsubscription requests 23 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [x] Allows subscribers to request a specific lease duration 25 | * If not, then describe the default lease duration issued, or other specifics here 26 | 27 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 28 | 29 | ## Distribution 30 | 31 | * [x] 100: Sends a notification with a matching content-type of the topic URL 32 | * [x] 100: Sends a notification with the full contents of the topic 33 | * [x] 101: Sends a notification with a valid signature 34 | * Please select the signature method(s) that the hub uses to sign requests 35 | * [ ] sha1 36 | * [x] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 40 | 41 | -------------------------------------------------------------------------------- /implementation-reports/HUB-pubsubhubbub-appspot-com.md: -------------------------------------------------------------------------------- 1 | # http://pubsubhubbub.appspot.com/ 2 | 3 | Implementation Home Page URL: http://pubsubhubbub.appspot.com/ 4 | 5 | Developer(s): [Google](https://www.google.com/) 6 | 7 | Answers are: 8 | * [X] Confirmed via websub.rocks (for applicable results) 9 | * [ ] All results are self-reported 10 | 11 | ## Subscription 12 | 13 | * [X] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 14 | * [X] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 15 | * [X] 102: Ignores unrecognized parameters in the subscription request 16 | * [X] 103: Allows subscribers to re-request active subscriptions before they expire 17 | * [X] 104: Supports unsubscription requests 18 | * [X] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 19 | * [X] Allows subscribers to request a specific lease duration 20 | * If not, then describe the default lease duration issued, or other specifics here 21 | 22 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 23 | 24 | ## Distribution 25 | 26 | * [X] 100: Sends a notification with a matching content-type of the topic URL 27 | * [X] 100: Sends a notification with the full contents of the topic 28 | * [X] 101: Sends a notification with a valid signature 29 | * Please select the signature method(s) that the hub uses to sign requests 30 | * [X] sha1 31 | * [ ] sha256 32 | * [ ] sha384 33 | * [ ] sha512 34 | * [X] Sends only a diff of the topic URL for Atom or RSS feeds 35 | 36 | -------------------------------------------------------------------------------- /implementation-reports/HUB-switchboard.md: -------------------------------------------------------------------------------- 1 | # Switchboard 2 | 3 | Implementation Home Page URL: 4 | 5 | Source code repo URL(s) (optional): 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): PHP 9 | 10 | Developer(s): [Aaron Parecki](https://aaronparecki.com) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [x] 104: Supports unsubscription requests 23 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [ ] Allows subscribers to request a specific lease duration 25 | * If not, then describe the default lease duration issued, or other specifics here 26 | * All subscriptions are for 1 week + 1 hour 27 | 28 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 29 | 30 | ## Distribution 31 | 32 | * [x] 100: Sends a notification with a matching content-type of the topic URL 33 | * [x] 100: Sends a notification with the full contents of the topic 34 | * [x] 101: Sends a notification with a valid signature 35 | * Please select the signature method(s) that the hub uses to sign requests 36 | * [ ] sha1 37 | * [x] sha256 38 | * [ ] sha384 39 | * [ ] sha512 40 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 41 | 42 | -------------------------------------------------------------------------------- /implementation-reports/HUB-twitch.md: -------------------------------------------------------------------------------- 1 | # Twitch 2 | 3 | Implementation Home Page URL: https://dev.twitch.tv/docs/api/webhooks-guide 4 | 5 | Source code repo URL(s) (optional): 6 | * [ ] 100% open source implementation 7 | 8 | Programming Language(s): Go 9 | 10 | Developer(s): [Jordan Potter](jordanpotter@twitch.tv) 11 | 12 | Answers are: 13 | * [ ] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [x] 104: Supports unsubscription requests 23 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [x] Allows subscribers to request a specific lease duration 25 | * If not, then describe the default lease duration issued, or other specifics here 26 | 27 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 28 | 29 | ## Distribution 30 | 31 | * [x] 100: Sends a notification with a matching content-type of the topic URL 32 | * [ ] 100: Sends a notification with the full contents of the topic 33 | * [x] 101: Sends a notification with a valid signature 34 | * Please select the signature method(s) that the hub uses to sign requests 35 | * [ ] sha1 36 | * [x] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 40 | -------------------------------------------------------------------------------- /implementation-reports/HUB-websub-superfeedr-com.md: -------------------------------------------------------------------------------- 1 | # http://websub.superfeedr.com/ 2 | 3 | Implementation Home Page URL: http://websub.superfeedr.com/ 4 | 5 | Developer(s): [Superfeedr](https://superfeedr.com/) 6 | 7 | Answers are: 8 | * [X] Confirmed via websub.rocks (for applicable results) 9 | * [ ] All results are self-reported 10 | 11 | ## Subscription 12 | 13 | * [X] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 14 | * [X] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 15 | * [X] 102: Ignores unrecognized parameters in the subscription request 16 | * [X] 103: Allows subscribers to re-request active subscriptions before they expire 17 | * [X] 104: Supports unsubscription requests 18 | * [X] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 19 | * [X] Allows subscribers to request a specific lease duration 20 | * If not, then describe the default lease duration issued, or other specifics here 21 | 22 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 23 | 24 | ## Distribution 25 | 26 | * [X] 100: Sends a notification with a matching content-type of the topic URL 27 | * [X] 100: Sends a notification with the full contents of the topic 28 | * [X] 101: Sends a notification with a valid signature 29 | * Please select the signature method(s) that the hub uses to sign requests 30 | * [X] sha1 31 | * [ ] sha256 32 | * [ ] sha384 33 | * [ ] sha512 34 | * [X] Sends only a diff of the topic URL for Atom or RSS feeds 35 | 36 | -------------------------------------------------------------------------------- /implementation-reports/HUB-websubhub.md: -------------------------------------------------------------------------------- 1 | # WebSubHub 2 | 3 | Implementation Home Page URL: https://websubhub.com 4 | 5 | Source code repo URL(s) (optional): https://github.com/clone1018/WebSubHub 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Elixir 9 | 10 | Developer(s): [clone1018](https://github.com/clone1018) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [x] 104: Supports unsubscription requests 23 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [x] Allows subscribers to request a specific lease duration 25 | * If not, then describe the default lease duration issued, or other specifics here 26 | 27 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 28 | 29 | ## Distribution 30 | 31 | * [x] 100: Sends a notification with a matching content-type of the topic URL 32 | * [x] 100: Sends a notification with the full contents of the topic 33 | * [x] 101: Sends a notification with a valid signature 34 | * Please select the signature method(s) that the hub uses to sign requests 35 | * [ ] sha1 36 | * [x] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 40 | 41 | -------------------------------------------------------------------------------- /implementation-reports/HUB-webubbub.md: -------------------------------------------------------------------------------- 1 | # Webubbub 2 | 3 | Implementation Home Page URL: [websub.flus.io](https://websub.flus.io/) 4 | 5 | Source code repo URL(s) (optional): [github.com/flusio/Webubbub](https://github.com/flusio/Webubbub) 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): PHP 9 | 10 | Developer(s): [Marien Fressinaud](https://marienfressinaud.fr) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [x] 104: Supports unsubscription requests 23 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [x] Allows subscribers to request a specific lease duration 25 | * The lease duration is limited between 1 day and 15 days to enforce short 26 | lived subscription. Default value is 10 days if `hub.lease_seconds` is not 27 | passed. 28 | 29 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 30 | 31 | ## Distribution 32 | 33 | * [x] 100: Sends a notification with a matching content-type of the topic URL 34 | * [x] 100: Sends a notification with the full contents of the topic 35 | * [x] 101: Sends a notification with a valid signature 36 | * Please select the signature method(s) that the hub uses to sign requests 37 | * [ ] sha1 38 | * [x] sha256 39 | * [ ] sha384 40 | * [ ] sha512 41 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 42 | -------------------------------------------------------------------------------- /implementation-reports/HUB-wso2-apim.md: -------------------------------------------------------------------------------- 1 | # WSO2 API Manager (4.1.0 onwards) 2 | 3 | Implementation Home Page URL: [WSO2-API-MANAGER websub | webhook](https://apim.docs.wso2.com/en/latest/tutorials/streaming-api/create-and-publish-websub-api/) 4 | 5 | Source code repo URL(s) (optional): 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Java, WSO2 Synapse 9 | 10 | Developer(s): [WSO2 API Manager](https://wso2.com/api-manager/) 11 | 12 | Answers are: 13 | * [ ] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Subscription 17 | 18 | * [x] 100: Supports subscriptions with `hub.mode`, `hub.topic` and `hub.callback` 19 | * [x] 101: Supports subscriptions with `hub.mode`, `hub.topic`, `hub.callback` and `hub.secret` 20 | * [x] 102: Ignores unrecognized parameters in the subscription request 21 | * [x] 103: Allows subscribers to re-request active subscriptions before they expire 22 | * [x] 104: Supports unsubscription requests 23 | * [x] 1xx: Sends a properly formatted verification request for subscribing and unsubscribing 24 | * [x] Allows subscribers to request a specific lease duration 25 | * If not, then describe the default lease duration issued, or other specifics here 26 | 27 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 28 | 29 | ## Distribution 30 | 31 | * [x] 100: Sends a notification with a matching content-type of the topic URL 32 | * [x] 100: Sends a notification with the full contents of the topic 33 | * [x] 101: Sends a notification with a valid signature 34 | * Please select the signature method(s) that the hub uses to sign requests 35 | * [x] sha1 36 | * [ ] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [ ] Sends only a diff of the topic URL for Atom or RSS feeds 40 | 41 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-TEMPLATE.md: -------------------------------------------------------------------------------- 1 | This file is a template implementation report for WebSub subscribers. Copy this file to a new .md file and change the name to `PUBLISHER-project-name.md`, your project name (lowercase with hyphens between words). Fill out the information based on the details of your implementation. It's okay to not check all the boxes, we are more interested in knowing how much of the spec is implemented than getting everyone to tick every box. When you are finished, submit a pull request or link to your file in a [new issue](https://github.com/w3c/websub/issues). 2 | 3 | For items that have a number next to the checkbox, the number corresponds with the test number on websub.rocks. You can use that tool to check whether you support the feature properly. To mark a statement as true, add an x between the brackets, e.g. [x]. If the statement does not apply to your implementation, use [na] and add a sentence explaining why it does not apply. 4 | 5 | Delete the section above when filling out your copy of this file. 6 | 7 | # Implementation Name (Replace this header) 8 | 9 | Implementation Home Page URL: 10 | 11 | Source code repo URL(s) (optional): 12 | * [ ] 100% open source implementation 13 | 14 | Programming Language(s): 15 | 16 | Developer(s): [Name](https://you.example.com) 17 | 18 | Answers are: 19 | * [ ] Confirmed via websub.rocks (for applicable results) 20 | * [ ] All results are self-reported 21 | 22 | ## Discovery 23 | 24 | * The publisher produces URLs with the following content types: 25 | * [ ] HTML 26 | * [ ] Atom 27 | * [ ] RSS 28 | * [ ] JSON 29 | * Other ________ 30 | * [ ] The publisher advertises the hub and self URLs in HTTP headers 31 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 32 | * [ ] HTML in tags in the HTML 33 | * [ ] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 34 | * [ ] Atom in elements 35 | * [ ] RSS in elements 36 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 37 | 38 | ## Distribution 39 | 40 | * [ ] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 41 | 42 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 43 | 44 | * [ ] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 45 | * [ ] Other: ______________________ 46 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-ballerina.md: -------------------------------------------------------------------------------- 1 | # Ballerina 2 | 3 | Implementation Home Page URL: [ballerina/websub](https://central.ballerina.io/ballerina/websubhub/latest#PublisherClient) 4 | 5 | Source code repo URL(s) (optional): https://github.com/ballerina-lang/ballerina 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ballerina 9 | 10 | Developer(s): [Ballerina](https://ballerina.io/) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * The publisher produces URLs with the following content types: 19 | * [ ] HTML 20 | * [ ] Atom 21 | * [ ] RSS 22 | * [ ] JSON 23 | * Other - The developer/user specifies the URLs. Util functions are available to add link headers. 24 | * [x] The publisher advertises the hub and self URLs in HTTP headers 25 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 26 | * [ ] HTML in tags in the HTML 27 | * [ ] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 28 | * [ ] Atom in elements 29 | * [ ] RSS in elements 30 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 31 | 32 | ## Distribution 33 | 34 | * [x] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 35 | 36 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 37 | 38 | * [x] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 39 | * [x] Other: Also allows sending a POST request, with the new content, to the hub with `hub 40 | .mode=publish&hub.topic=_______` 41 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-diaspora.md: -------------------------------------------------------------------------------- 1 | # Diaspora 2 | 3 | Implementation Home Page URL: https://diasporafoundation.org/ 4 | 5 | Source code repo URL(s) (optional): 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ruby 9 | 10 | Developer(s): [Diaspora Community](https://github.com/diaspora/diaspora/graphs/contributors) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * The publisher produces URLs with the following content types: 19 | * [ ] HTML 20 | * [x] Atom 21 | * [ ] RSS 22 | * [ ] JSON 23 | * Other ________ 24 | * [ ] The publisher advertises the hub and self URLs in HTTP headers 25 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 26 | * [ ] HTML in tags in the HTML 27 | * [ ] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 28 | * [x] Atom in elements 29 | * [ ] RSS in elements 30 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 31 | 32 | ## Distribution 33 | 34 | * [x] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 35 | 36 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 37 | 38 | * [ ] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 39 | * [x] Other: POST request to the hub with `hub.mode=publish&hub.url=_______` 40 | 41 | ## Notes 42 | 43 | * This is not reported by the diaspora team, but by a third party on their behalf of current released code. 44 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-dobrado.md: -------------------------------------------------------------------------------- 1 | # Dobrado 2 | 3 | Implementation Home Page URL: https://dobrado.net 4 | 5 | Source code repo URL(s) (optional): https://gitlab.com/dobrado/dobrado 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): PHP 9 | 10 | Developer(s): [Malcolm Blaney](https://unicyclic.com/mal) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * The publisher produces URLs with the following content types: 19 | * [x] HTML 20 | * [ ] Atom 21 | * [x] RSS 22 | * [ ] JSON 23 | * Other ________ 24 | * [x] The publisher advertises the hub and self URLs in HTTP headers 25 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 26 | * [ ] HTML in tags in the HTML 27 | * [ ] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 28 | * [ ] Atom in elements 29 | * [ ] RSS in elements 30 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 31 | 32 | ## Distribution 33 | 34 | * [x] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 35 | 36 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 37 | 38 | * [ ] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 39 | * [ ] Other: ______________________ 40 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-falcon.md: -------------------------------------------------------------------------------- 1 | # Falcon 2 | 3 | Implementation Home Page URL: https://indieweb.org/Falcon 4 | 5 | Source code repo URL(s) (optional): 6 | * [ ] 100% open source implementation 7 | 8 | Programming Language(s): PHP, Javascript 9 | 10 | Developer(s): [Tantek Çelik](http://tantek.com) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * The publisher produces URLs with the following content types: 19 | * [x] HTML 20 | * [x] Atom 21 | * [ ] RSS 22 | * [ ] JSON 23 | * Other ________ 24 | * [ ] The publisher advertises the hub and self URLs in HTTP headers 25 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 26 | * [x] HTML in `` tags in the HTML `` 27 | * [ ] HTML in `` tags in the body (currently not allowed, but the restriction of placing the `` tags in the `` is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 28 | * [x] Atom in `` elements 29 | * [ ] RSS in `` elements 30 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 31 | 32 | ## Distribution 33 | 34 | * [x] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 35 | 36 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 37 | 38 | * [ ] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 39 | * [x] Other: The publisher sends POST requests to the hub with `hub.mode=publish&hub.url=http%3A%2F%2Ftantek.com%2F` and `hub.mode=publish&hub.url=http%3A%2F%2Ftantek.com%2Fupdates.atom` 40 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-flask-websub.md: -------------------------------------------------------------------------------- 1 | # Flask-WebSub 2 | 3 | An implementation of a WebSub hub, publisher and subscriber as a Flask 4 | extension. The implementation is meant to be used as a library that can be 5 | integrated in a larger application. 6 | 7 | Implementation Home Page URL: https://github.com/marten-de-vries/Flask-WebSub 8 | 9 | Source code repo URL(s): https://github.com/marten-de-vries/Flask-WebSub 10 | * [x] 100% open source implementation 11 | 12 | Programming Language(s): Python 3 (with the Flask, Celery and requests 13 | libraries) 14 | 15 | Developer(s): [Marten de Vries](https://ma.rtendevri.es) 16 | 17 | Answers are: 18 | * [x] Confirmed via websub.rocks (for applicable results) 19 | * [ ] All results are self-reported 20 | 21 | ## Discovery 22 | 23 | * The publisher produces URLs with the following content types: 24 | * [x] HTML 25 | * [ ] Atom 26 | * [ ] RSS 27 | * [ ] JSON 28 | * [x] Other: It's a library. A user can add it around a Flask route of any 29 | content type. That said, there are special helper functions for html 30 | tags. Link headers are always set automatically. 31 | * [x] The publisher advertises the hub and self URLs in HTTP headers 32 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 33 | * [na] HTML in tags in the HTML 34 | * [na] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 35 | * [na] Atom in elements 36 | * [na] RSS in elements 37 | * There is a helper for creating a link tag, the user decides where to use 38 | it in their Flask route. 39 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 40 | 41 | ## Distribution 42 | 43 | * [na] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 44 | * Up to the user. A library does not know when the underlying data store changes. 45 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 46 | 47 | * [ ] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 48 | * [ ] Other: ______________________ 49 | * Publishing to an integrated hub is a single function call. To an external hub 50 | is up to the user completely. 51 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-mastodon.md: -------------------------------------------------------------------------------- 1 | # Mastodon 2 | 3 | Implementation Home Page URL: https://mastodon.social/ 4 | 5 | Source code repo URL(s) (optional): 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ruby 9 | 10 | Developer(s): [Eugen Rochko](https://github.com/Gargron) 11 | 12 | Answers are: 13 | * [ ] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | Note: Answers were reported in IRC by Eugen Rochko and transcribed to this report by Aaron Parecki. https://chat.indieweb.org/social/2017-07-12#t1499876947598000 17 | 18 | ## Discovery 19 | 20 | * The publisher produces URLs with the following content types: 21 | * [ ] HTML 22 | * [x] Atom 23 | * [ ] RSS 24 | * [ ] JSON 25 | * Other ________ 26 | * [ ] The publisher advertises the hub and self URLs in HTTP headers 27 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 28 | * [ ] HTML in tags in the HTML 29 | * [ ] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 30 | * [x] Atom in elements 31 | * [ ] RSS in elements 32 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 33 | 34 | ## Distribution 35 | 36 | * [x] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 37 | 38 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 39 | 40 | * [ ] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 41 | * [ ] Other: ______________________ 42 | -------------------------------------------------------------------------------- /implementation-reports/PUBLISHER-wordpress-pubsubhubbub.md: -------------------------------------------------------------------------------- 1 | # WordPress WebSub/PubSubHubbub plugin 2 | 3 | Implementation Home Page URL: https://wordpress.org/plugins/pubsubhubbub/ 4 | 5 | Source code repo URL(s): https://github.com/pubsubhubbub/wordpress-pubsubhubbub 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): PHP 9 | 10 | Developer(s): [Matthias Pfefferle](https://notiz.blog), [Josh Fraser](https://www.onlineaspect.com) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * The publisher produces URLs with the following content types: 19 | * [x] HTML 20 | * [x] Atom 21 | * [x] RSS 22 | * [x] JSON 23 | * [x] expandable by other plugins, no content type limitations 24 | * [x] The publisher advertises the hub and self URLs in HTTP headers 25 | * The publisher advertises the hub and self URLs in the body of the document for the following content types: 26 | * [ ] HTML in tags in the HTML 27 | * [ ] HTML in tags in the body (currently not allowed, but the restriction of placing the tags in the is *at risk* so if an implementation requires advertising the URLs in the body this limitation may be dropped) 28 | * [x] Atom in elements 29 | * [x] RSS in elements 30 | * [ ] The publisher advertises the hub URL using the `.host-meta` well-known URI (currently *at risk*) 31 | 32 | ## Distribution 33 | 34 | * [x] The publisher notifies the hub when a topic has been updated. (This is required, although the implementation details are not specified, in order to allow flexibility in how hubs are implemented. e.g. a hub integrated with the publishing software does not need a standardized notification mechanism.) 35 | 36 | If your publisher uses an external hub, please describe how the publisher notifies the hub of new content: 37 | 38 | * [x] The publisher sends a POST request to the hub with `hub.mode=publish&hub.topic=_______` 39 | * [ ] Other: ______________________ 40 | -------------------------------------------------------------------------------- /implementation-reports/README.md: -------------------------------------------------------------------------------- 1 | # Implementation Reports 2 | 3 | This folder is where you can find implementation reports that have been submitted. 4 | 5 | To submit your own implementation report, copy the appropriate template file to a new `.md` file with the name of your implementation, and check the boxes for any features that your implementation supports. 6 | 7 | Implementation report templates are available for publishers, subscribers, and hubs. 8 | 9 | * [`SUBSCRIBER-TEMPLATE.md`](SUBSCRIBER-TEMPLATE.md) 10 | * [`PUBLISHER-TEMPLATE.md`](PUBLISHER-TEMPLATE.md) 11 | * [`HUB-TEMPLATE.md`](HUB-TEMPLATE.md) 12 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-TEMPLATE.md: -------------------------------------------------------------------------------- 1 | This file is a template implementation report for WebSub subscribers. Copy this file to a new .md file and change the name to `SUBSCRIBER-project-name.md`, your project name (lowercase with hyphens between words). Fill out the information based on the details of your implementation. It's okay to not check all the boxes, we are more interested in knowing how much of the spec is implemented than getting everyone to tick every box. When you are finished, submit a pull request or link to your file in a [new issue](https://github.com/w3c/websub/issues). 2 | 3 | For items that have a number next to the checkbox, the number corresponds with the test number on websub.rocks. You can use that tool to check whether you support the feature properly. To mark a statement as true, add an x between the brackets, e.g. [x]. If the statement does not apply to your implementation, use [na] and add a sentence explaining why it does not apply. 4 | 5 | Delete the section above when filling out your copy of this file. 6 | 7 | # Implementation Name (Replace this header) 8 | 9 | Implementation Home Page URL: 10 | 11 | Source code repo URL(s) (optional): 12 | * [ ] 100% open source implementation 13 | 14 | Programming Language(s): 15 | 16 | Developer(s): [Name](https://you.example.com) 17 | 18 | Answers are: 19 | * [ ] Confirmed via websub.rocks (for applicable results) 20 | * [ ] All results are self-reported 21 | 22 | ## Discovery 23 | 24 | * [ ] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 25 | * [ ] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 26 | * [ ] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 27 | * [ ] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 28 | * [ ] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 29 | 30 | ## Subscription 31 | 32 | * [ ] 1xx: Successfully creates a subscription 33 | * [ ] 200: Subscribing to a URL that reports a different rel=self 34 | * [ ] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 35 | * [ ] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 36 | * [ ] 203: Subscribing to a hub that sends a 302 temporary redirect 37 | * [ ] 204: Subscribing to a hub that sends a 301 permanent redirect 38 | * [ ] 205: Rejects a verification request with an invalid topic URL 39 | * [ ] 1xx: Requests a subscription using a secret (optional) 40 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 41 | * [ ] sha1 42 | * [ ] sha256 43 | * [ ] sha384 44 | * [ ] sha512 45 | * [ ] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 46 | * [ ] Callback URL is unique per subscription (should) 47 | * [ ] Callback URL is an unguessable URL (should) 48 | * [ ] 1xx: Sends an unsubscription request 49 | 50 | ## Distribution 51 | 52 | * [ ] 300: Returns HTTP 2xx when the notification payload is delivered 53 | * [ ] 1xx: Verifies a valid signature for authenticated distribution 54 | * [ ] 301: Rejects a distribution request with an invalid signature 55 | * [ ] 302: Rejects a distribution request with no signature when the subscription was made with a secret 56 | 57 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 58 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-ballerina.md: -------------------------------------------------------------------------------- 1 | # Ballerina 2 | 3 | Implementation Home Page URL: [ballerina/websub](https://central.ballerina.io/ballerina/websub/latest) 4 | 5 | Source code repo URL(s) (optional): https://github.com/ballerina-lang/ballerina 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ballerina 9 | 10 | Developer(s): [Ballerina](https://ballerina.io/) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [ ] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * [x] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 19 | * [ ] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 20 | * [ ] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 21 | * [ ] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 22 | * [x] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 23 | 24 | ## Subscription 25 | 26 | * [x] 1xx: Successfully creates a subscription 27 | * [x] 200: Subscribing to a URL that reports a different rel=self 28 | * [x] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 29 | * [x] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 30 | * [x] 203: Subscribing to a hub that sends a 302 temporary redirect 31 | * [x] 204: Subscribing to a hub that sends a 301 permanent redirect 32 | * [x] 205: Rejects a verification request with an invalid topic URL 33 | * [x] 1xx: Requests a subscription using a secret (optional) 34 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 35 | * [x] sha1 36 | * [x] sha256 37 | * [x] sha384 38 | * [x] sha512 39 | * [x] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 40 | * [x] Callback URL is unique per subscription (should) 41 | * Developer specifies the URL 42 | * [x] Callback URL is an unguessable URL (should) 43 | * Developer specifies the URL 44 | * [x] 1xx: Sends an unsubscription request 45 | 46 | ## Distribution 47 | 48 | * [x] 300: Returns HTTP 2xx when the notification payload is delivered 49 | * [x] 1xx: Verifies a valid signature for authenticated distribution 50 | * [x] 301: Rejects a distribution request with an invalid signature 51 | * [x] 302: Rejects a distribution request with no signature when the subscription was made with a secret 52 | 53 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 54 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-dobrado.md: -------------------------------------------------------------------------------- 1 | # Dobrado 2 | 3 | Implementation Home Page URL: https://dobrado.net 4 | 5 | Source code repo URL(s) (optional): https://gitlab.com/dobrado/dobrado 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): PHP 9 | 10 | Developer(s): [Malcolm Blaney](https://unicyclic.com/mal) 11 | 12 | Answers are: 13 | * [x] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * [x] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 19 | * [x] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 20 | * [x] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 21 | * [x] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 22 | * [x] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 23 | 24 | ## Subscription 25 | 26 | * [x] 1xx: Successfully creates a subscription 27 | * [x] 200: Subscribing to a URL that reports a different rel=self 28 | * [x] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 29 | * [x] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 30 | * [x] 203: Subscribing to a hub that sends a 302 temporary redirect 31 | * [x] 204: Subscribing to a hub that sends a 301 permanent redirect 32 | * [x] 205: Rejects a verification request with an invalid topic URL 33 | * [ ] 1xx: Requests a subscription using a secret (optional) 34 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 35 | * [ ] sha1 36 | * [ ] sha256 37 | * [ ] sha384 38 | * [ ] sha512 39 | * [ ] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 40 | * [x] Callback URL is unique per subscription (should) 41 | * [x] Callback URL is an unguessable URL (should) 42 | * [ ] 1xx: Sends an unsubscription request 43 | 44 | ## Distribution 45 | 46 | * [x] 300: Returns HTTP 2xx when the notification payload is delivered 47 | * [ ] 1xx: Verifies a valid signature for authenticated distribution 48 | * [ ] 301: Rejects a distribution request with an invalid signature 49 | * [ ] 302: Rejects a distribution request with no signature when the subscription was made with a secret 50 | 51 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 52 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-feedmail.md: -------------------------------------------------------------------------------- 1 | # FeedMail 2 | 3 | Implementation Home Page URL: https://feedmail.org 4 | 5 | Source code repo URL(s) (optional): 6 | * [ ] 100% open source implementation 7 | 8 | Programming Language(s): Rust 9 | 10 | Developer(s): [Kevin Cox](https://kevincox.ca) 11 | 12 | Answers are: 13 | * [ ] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | ## Discovery 17 | 18 | * [x] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 19 | * [ ] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 20 | * [x] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 21 | * [x] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 22 | * [x] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 23 | 24 | ## Subscription 25 | 26 | * [x] 1xx: Successfully creates a subscription 27 | * [ ] 200: Subscribing to a URL that reports a different rel=self 28 | * Note: Due to concerns about misconfigured feeds FeedMail currently ignores WebSub where the self link differs substantially from the feed URL and falls back to polling. 29 | * [x] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 30 | * [x] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 31 | * [x] 203: Subscribing to a hub that sends a 302 temporary redirect 32 | * [x] 204: Subscribing to a hub that sends a 301 permanent redirect 33 | * [x] 205: Rejects a verification request with an invalid topic URL 34 | * [ ] 1xx: Requests a subscription using a secret (optional) 35 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 36 | * [ ] sha1 37 | * [ ] sha256 38 | * [ ] sha384 39 | * [ ] sha512 40 | * [x] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 41 | * [x] Callback URL is unique per subscription (should) 42 | * [x] Callback URL is an unguessable URL (should) 43 | * [ ] 1xx: Sends an unsubscription request 44 | 45 | ## Distribution 46 | 47 | * [x] 300: Returns HTTP 2xx when the notification payload is delivered 48 | * [ ] 1xx: Verifies a valid signature for authenticated distribution 49 | * [x] 301: Rejects a distribution request with an invalid signature 50 | * [ ] 302: Rejects a distribution request with no signature when the subscription was made with a secret 51 | 52 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 53 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-flask-websub.md: -------------------------------------------------------------------------------- 1 | # Flask-WebSub 2 | 3 | An implementation of a WebSub hub, publisher and subscriber as a Flask 4 | extension. The implementation is meant to be used as a library that can be 5 | integrated in a larger application. 6 | 7 | Implementation Home Page URL: https://github.com/marten-de-vries/Flask-WebSub 8 | 9 | Source code repo URL(s): https://github.com/marten-de-vries/Flask-WebSub 10 | * [x] 100% open source implementation 11 | 12 | Programming Language(s): Python 3 (with the Flask, Celery and requests 13 | libraries) 14 | 15 | Developer(s): [Marten de Vries](https://ma.rtendevri.es) 16 | 17 | Answers are: 18 | * [x] Confirmed via websub.rocks (for applicable results) 19 | * [ ] All results are self-reported 20 | 21 | ## Discovery 22 | 23 | * [x] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 24 | * [x] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 25 | * [x] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 26 | * [x] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 27 | * [x] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 28 | 29 | ## Subscription 30 | 31 | Note that due to https://github.com/aaronpk/websub.rocks/issues/15, the 32 | subscription reqest connnection actually times out waiting for a 202 response. 33 | This results in an error message being shown. Still, as all the required 34 | processing has happened by then, it does not otherwise hamper running the 35 | tests. 36 | 37 | * [x] 1xx: Successfully creates a subscription 38 | * [x] 200: Subscribing to a URL that reports a different rel=self 39 | * [x] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 40 | * [x] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 41 | * [x] 203: Subscribing to a hub that sends a 302 temporary redirect 42 | * [x] 204: Subscribing to a hub that sends a 301 permanent redirect 43 | * [x] 205: Rejects a verification request with an invalid topic URL 44 | * [x] 1xx: Requests a subscription using a secret (optional) 45 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 46 | * [x] sha1 47 | * [x] sha256 48 | * [x] sha384 49 | * [x] sha512 50 | * [x] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 51 | * [x] Callback URL is unique per subscription (should) 52 | * [x] Callback URL is an unguessable URL (should) 53 | * [x] 1xx: Sends an unsubscription request 54 | 55 | ## Distribution 56 | 57 | * [x] 300: Returns HTTP 2xx when the notification payload is delivered 58 | * [x] 1xx: Verifies a valid signature for authenticated distribution 59 | * [x] 301: Rejects a distribution request with an invalid signature 60 | * [x] 302: Rejects a distribution request with no signature when the subscription was made with a secret 61 | 62 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 63 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-mastodon.md: -------------------------------------------------------------------------------- 1 | # Mastodon 2 | 3 | Implementation Home Page URL: https://mastodon.social/ 4 | 5 | Source code repo URL(s) (optional): 6 | * [x] 100% open source implementation 7 | 8 | Programming Language(s): Ruby 9 | 10 | Developer(s): [Eugen Rochko](https://github.com/Gargron) 11 | 12 | Answers are: 13 | * [ ] Confirmed via websub.rocks (for applicable results) 14 | * [x] All results are self-reported 15 | 16 | Note: Answers were reported in IRC by Eugen Rochko and transcribed to this report by Aaron Parecki. https://chat.indieweb.org/social/2017-07-12#t1499876947598000 17 | 18 | ## Discovery 19 | 20 | * [ ] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 21 | * [ ] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 22 | * [x] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 23 | * [ ] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 24 | * [ ] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 25 | 26 | ## Subscription 27 | 28 | * [x] 1xx: Successfully creates a subscription 29 | * [ ] 200: Subscribing to a URL that reports a different rel=self 30 | * [ ] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 31 | * [ ] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 32 | * [ ] 203: Subscribing to a hub that sends a 302 temporary redirect 33 | * [ ] 204: Subscribing to a hub that sends a 301 permanent redirect 34 | * [x] 205: Rejects a verification request with an invalid topic URL 35 | * [ ] 1xx: Requests a subscription using a secret (optional) 36 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 37 | * [x] sha1 38 | * [ ] sha256 39 | * [ ] sha384 40 | * [ ] sha512 41 | * [x] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 42 | * [x] Callback URL is unique per subscription (should) 43 | * [ ] Callback URL is an unguessable URL (should) 44 | * [x] 1xx: Sends an unsubscription request 45 | 46 | ## Distribution 47 | 48 | * [x] 300: Returns HTTP 2xx when the notification payload is delivered 49 | * [x] 1xx: Verifies a valid signature for authenticated distribution 50 | * [x] 301: Rejects a distribution request with an invalid signature 51 | * [x] 302: Rejects a distribution request with no signature when the subscription was made with a secret 52 | -------------------------------------------------------------------------------- /implementation-reports/SUBSCRIBER-superfeedr.com.md: -------------------------------------------------------------------------------- 1 | # superfeedr.com 2 | 3 | Superfeedr will act as a subscriber when provided with a topic to poll on behalf of one of our customers. 4 | 5 | Implementation Home Page URL: https://superfeedr.com 6 | 7 | Answers are: 8 | * [X] Confirmed via websub.rocks (for applicable results) 9 | * [ ] All results are self-reported 10 | 11 | ## Discovery 12 | 13 | * [X] 100: HTTP header discovery - discovers the hub and self URLs from HTTP headers 14 | * [X] 101: HTML tag discovery - discovers the hub and self URLs from the HTML `` tags 15 | * [X] 102: Atom feed discovery - discovers the hub and self URLs from the XML `` tags 16 | * [X] 103: RSS feed discovery - discovers the hub and self URLs from the XML `` tags 17 | * [X] 104: Discovery priority - prioritizes the hub and self in HTTP headers over the links in the body 18 | 19 | ## Subscription 20 | 21 | * [X] 1xx: Successfully creates a subscription 22 | * [X] 200: Subscribing to a URL that reports a different rel=self 23 | * [X] 201: Subscribing to a topic URL that sends an HTTP 302 temporary redirect 24 | * [X] 202: Subscribing to a topic URL that sends an HTTP 301 permanent redirect 25 | * [0] 203: Subscribing to a hub that sends a 302 temporary redirect 26 | Not currently supported by Superfeedr. on roadmap 27 | * [0] 204: Subscribing to a hub that sends a 301 permanent redirect 28 | Not currently supported by Superfeedr. on roadmap 29 | * [0] 205: Rejects a verification request with an invalid topic URL 30 | The test fails... i have to look into this 31 | * [X] 1xx: Requests a subscription using a secret (optional) 32 | * Please select the signature method(s) that the subscriber recognizes. All methods listed below are currently acceptable for the hub to choose: 33 | * [X] sha1 34 | * [ ] sha256 35 | * [ ] sha384 36 | * [ ] sha512 37 | * [X] 1xx: Requests a subscription with a specific `lease_seconds` (optional, hub may ignore) 38 | * [X] Callback URL is unique per subscription (should) 39 | * [?] Callback URL is an unguessable URL (should) 40 | We're using sequences of numbers... BUT they're probably not unguessable by brute force. On roadmap 41 | * [X] 1xx: Sends an unsubscription request 42 | 43 | ## Distribution 44 | 45 | * [X] 300: Returns HTTP 2xx when the notification payload is delivered 46 | * [X] 1xx: Verifies a valid signature for authenticated distribution 47 | * [X] 301: Rejects a distribution request with an invalid signature 48 | * [X] 302: Rejects a distribution request with no signature when the subscription was made with a secret 49 | 50 | (1xx denotes that you can can use any of the 100-104 tests to confirm this feature) 51 | -------------------------------------------------------------------------------- /source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebSub 6 | 7 | 8 | 10 | 120 | 121 | 122 | 123 | 124 | 125 |
126 |

WebSub provides a common mechanism for communication between publishers of any kind of Web content and their subscribers, based on HTTP web hooks. Subscription requests are relayed through hubs, which validate and verify the request. Hubs then distribute new and updated content to subscribers when it becomes available. WebSub was previously known as PubSubHubbub.

127 |
128 | 129 |
130 | 131 |
132 |

Definitions

133 |
134 |
Topic
135 |
An HTTP [[!RFC7230]] (or HTTPS [[!RFC2818]]) resource URL. The unit to which one can subscribe to changes.
136 |
Hub ("the hub")
137 |
The server (URL [[!URL]]) which implements both sides of this protocol. Any hub MAY implement its own policies on who can use it.
138 |
Publisher
139 |
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".
140 |
Subscriber
141 |
An entity (person or program) that wants to be notified of changes on a topic. The subscriber must be directly network-accessible and is identified by its Subscriber Callback URL.
142 |
Subscription
143 |
A unique relation to a topic by a subscriber that indicates it should receive updates for that topic. A subscription's unique key is the tuple (Topic URL, Subscriber Callback URL). Subscriptions may (at the hub's decision) have expiration times akin to DHCP leases which must be periodically renewed.
144 |
Subscriber Callback URL
145 |
The URL [[!URL]] at which a subscriber wishes to receive content distribution requests.
146 |
Event
147 |
An event that causes updates to multiple topics. For each event that happens (e.g. "Brad posted to the Linux Community."), multiple topics could be affected (e.g. "Brad posted." and "Linux community has new post"). Publisher events cause topics to be updated and the hub looks up all subscriptions for affected topics, delivering the content to subscribers.
148 |
Content Distribution Notification / (Content Distribution Request)
149 |
A payload describing how a topic's contents have changed, or the full updated content. Depending on the topic's content type, the difference (or "delta") may be computed by the hub and sent to all subscribers.
150 |
151 |
152 | 153 |
154 |

High-level protocol flow

155 |

(This section is non-normative.)

156 | WebSub Flow Diagram Subscriber Publisher Hub Subscriber discovers the hub advertised by publisher's topic Subscriber makes a POST to the hub to subscribe to updates about topic Hub verifies the subscription attempt with a GET Publisher notifies the hub of new content Hub delivers the contents of topicto each subscriber with a POST 157 | 158 |
    159 |
  • Subscribers discover the hub of a topic URL, and makes a POST to one or more of the advertised hubs in order to receive updates when the topic changes.
  • 160 |
  • Publishers notify their hub(s) URLs when their topic(s) change.
  • 161 |
  • When the hub identifies a change in the topic, it sends a content distribution notification to all registered subscribers.
  • 162 |
163 |

Earlier versions of this protocol were called PubSubHubbub:

164 |
    165 |
  • Working Draft 0.3 [[PubSubHubbub-Core-0.3]]
  • 166 |
  • Working Draft 0.4 [[PubSubHubbub-Core-0.4]]
  • 167 |
168 |
169 | 170 |
171 |

Conformance

172 | 173 |

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 174 | "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 175 | document are to be interpreted as described in [[!RFC2119]].

176 | 177 |
178 |

Conformance Classes

179 | 180 |

WebSub describes three roles: publishers, subscribers and hubs. This section describes the conformance criteria for each role.

181 | 182 |

Publishers

183 | 184 |
    185 |
  • A conforming publisher MUST advertise topic and hub URLs for a given resource URL as described in Discovery.
  • 186 |
187 | 188 |

Subscribers

189 | 190 |

A conforming subscriber:

191 | 192 |
    193 |
  • MUST support each discovery mechanism in the specified order to discover the topic and hub URLs as described in Discovery.
  • 194 |
  • MUST send a subscription request as described in Subscriber Sends Subscription Request.
  • 195 |
  • MAY request a specific lease duration
  • 196 |
  • MAY include a secret in the subscription request, and if it does, then MUST use the secret to verify the signature in the content distribution request.
  • 197 |
  • MUST acknowledge a content distribution request with an HTTP 2xx status code.
  • 198 |
  • MAY request that a subscription is deactivated using the "unsubscribe" mechanism.
  • 199 |
200 | 201 |

Hubs

202 | 203 |

A conforming hub:

204 | 205 |
    206 |
  • MUST accept a subscription request with the parameters hub.callback, hub.mode and hub.topic.
  • 207 |
  • MUST accept a subscription request with a hub.secret parameter.
  • 208 |
  • MAY respect the requested lease duration in subscription requests.
  • 209 |
  • MUST allow subscribers to re-request already active subscriptions.
  • 210 |
  • MUST support unsubscription requests.
  • 211 |
  • MUST send content distribution requests with a matching content type of the topic URL. (See Content Negotiation)
  • 212 |
  • MAY reduce the payload of the content distribution to a diff of the contents for supported formats as described in Content Distribution.
  • 213 |
  • MUST send a X-Hub-Signature header if the subscription was made with a hub.secret as described in Authenticated Content Distribution.
  • 214 |
215 | 216 |
217 |
218 |

Candidate Recommendation Exit Criteria

219 | 220 |

This specification exited the CR stage with at least two independent, interoperable implementations of each feature. Each feature may have been implemented by a different set of products. There was no requirement that all features be implemented by a single product. For the purposes of this criterion, we define the following terms:

221 | 222 |
223 |

Publisher

224 |

A WebSub Publisher is an implementation that advertises a topic and hub URL on one or more resource URLs. The conformance criteria are described in Conformance Classes above.

225 |
226 | 227 |
228 |

Subscriber

229 |

A WebSub Subscriber is an implementation that discovers the hub and topic URL given a resource URL, subscribes to updates at the hub, and accepts content distribution requests from the hub. The subscriber MAY support authenticated content distribution. The conformance criteria are described in Conformance Classes above.

230 |
231 | 232 |
233 |

Hub

234 |

A WebSub Hub is an implementation that handles subscription requests and distributes the content to subscribers when the corresponding topic URL has been updated. Hubs MUST support subscription requests with a secret and deliver authenticated requests when requested. Hubs MUST deliver the full contents of the topic URL in the request, and MAY reduce the payload to a diff if the content type supports it. The conformance criteria are described in Conformance Classes above.

235 |
236 | 237 |
238 |

Independent

239 |

Each implementation must be developed by a different party and cannot share, reuse, or derive from code used by another qualifying implementation. Sections of code that have no bearing on the implementation of this specification are exempt from this requirement.

240 |
241 | 242 |
243 |

Interoperable

244 |

A Subscriber and Hub implementation are considered interoperable for a specific feature when the Hub takes the defined action that the Subscriber requests, the Subscriber gets the expected response from a Hub according to the feature, and the Hub sends the expected response to the Subscriber.

245 |
246 | 247 |
248 |

Feature

249 |

For the purposes of evaluating exit criteria, each of the following is considered a feature:

250 |
    251 |
  • Discovering the hub and topic URLs by looking at the HTTP headers of the resource URL.
  • 252 |
  • Discovering the hub and topic URLs by looking at the contents of the resource URL as an XML document.
  • 253 |
  • Discovering the hub and topic URLs by looking at the contents of the resource URL as an HTML document.
  • 254 |
  • Subscribing to the hub with a callback URL.
  • 255 |
  • Subscribing to the hub and requesting a specific lease duration.
  • 256 |
  • Subscribing to the hub with a secret and handling authenticated content distribution.
  • 257 |
  • Requesting that a subscription is deactivated by sending an unsubscribe request.
  • 258 |
  • The Subscriber acknowledges a pending subscription on a validation request.
  • 259 |
  • The Subscriber rejects a subscription validation request for an invalid topic URL.
  • 260 |
  • The Subscriber returns an HTTP 2xx response when the payload is delivered.
  • 261 |
  • The Subscriber verifies the signature for authenticated content distribution requests.
  • 262 |
  • The Subscriber rejects the distribution request if the signature does not validate.
  • 263 |
  • The Subscriber rejects the distribution request when no signature is present if the subscription was made with a secret.
  • 264 |
  • The Hub respects the requested lease duration during a subscription request.
  • 265 |
  • The Hub allows Subscribers to re-request already active subscriptions, extending the lease duration.
  • 266 |
  • The Hub sends the full contents of the topic URL in the distribution request.
  • 267 |
  • The Hub sends a diff of the topic URL for the formats that support it.
  • 268 |
  • The Hub sends a valid signature for subscriptions that were made with a secret.
  • 269 |
270 |
271 | 272 |
273 |
274 | 275 |
276 |

Discovery

277 |

The discovery mechanism aims at identifying at least 2 URLs.

278 |
    279 |
  • The URL of one or more hubs designated by the publisher. If more than one hub URL is specified, it is expected that the publisher notifies each hub, so the subscriber may subscribe to one or more of them.
  • 280 |
  • The canonical URL for the topic to which subscribers are expected to use for subscriptions.
  • 281 |
282 |

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 hubs is a way to increase the likelihood of delivery to subscribers. As such, subscribers may subscribe to one or more of the advertised hubs.

283 |

The protocol currently supports the following discovery mechanisms. Publishers MUST implement at least one of them:

284 |
    285 |
  • Link Headers [[!RFC5988]]: the publisher SHOULD include at least one Link Header [[!RFC5988]] with rel=hub (a hub link header) as well as exactly one Link Header [[!RFC5988]] with rel=self (the self link header)
  • 286 |
  • If the topic is an XML based feed, publishers SHOULD use embedded link elements as described in Appendix B of Web Linking [[!RFC5988]]. Similarly, for HTML pages, publishers SHOULD use embedded link elements as described in Appendix A of Web Linking [[!RFC5988]].
  • 287 |
288 | 289 |

Since <link> has been limited to being placed in the <head> for many years, some consuming code might only check the <head>. Therefore it is more robust to place the <link> tags only in the HTML <head> rather than in the <body>.

290 | 291 |
GET /feed HTTP/1.1
292 | Host: example.com
293 | 
294 | HTTP/1.1 200 Ok
295 | Content-type: text/html
296 | Link: <https://hub.example.com/>; rel="hub"
297 | Link: <http://example.com/feed>; rel="self"
298 | 
299 | <!doctype html>
300 | <html>
301 |   <head>
302 |     <link rel="hub" href="https://hub.example.com/">
303 |     <link rel="self" href="http://example.com/feed">
304 |   </head>
305 |   <body>
306 |     ...
307 |   </body>
308 | </html>
309 |     
310 | 311 |

When perfoming discovery, subscribers MUST implement all two discovery mechanisms in the following order, stopping at the first match:

312 |
    313 |
  1. Issue a GET or HEAD request to retrieve the topic URL. Subscribers MUST check for HTTP Link headers first.
  2. 314 |
  3. In the absence of HTTP Link headers, and if the topic is an XML based feed or an HTML page, subscribers MUST check for embedded link elements.
  4. 315 |
316 | 317 |
318 |

Content Negotiation

319 |

320 | 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. 321 |

322 |

323 | 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 /feed with an Accept header containing application/json could return a rel=self value of /feed.json. 324 |

325 |

The example below illustrates how a topic URL can return different Link headers depending on the Accept header that was sent.

326 |
GET /feed HTTP/1.1
327 | Host: example.com
328 | Accept: application/json
329 | 
330 | HTTP/1.1 200 Ok
331 | Content-type: application/json
332 | Link: </feed.json>; rel="self"
333 | Link: <https://hub.example.com/>; rel="hub"
334 | 
335 | {
336 |   "items": [...]
337 | }
338 |
GET /feed HTTP/1.1
339 | Host: example.com
340 | Accept: text/html
341 | 
342 | HTTP/1.1 200 Ok
343 | Content-type: text/html
344 | Link: </feed.html>; rel="self"
345 | Link: <https://hub.example.com/>; rel="hub"
346 | 
347 | <html>
348 | ...
349 |

Similarly, the technique can also be used to return a different rel=self URL depending on the language requested by the Accept-Language header.

350 |
GET /feed HTTP/1.1
351 | Host: example.com
352 | Accept-Language: de-DE
353 | 
354 | HTTP/1.1 200 Ok
355 | Content-type: application/json
356 | 
357 | Link: </feed-de.json>; rel="self"
358 | Link: <https://hub.example.com/>; rel="hub"
359 | 
360 | {
361 |   "items": [...]
362 | }
363 | 364 |
365 | 366 |
367 | 368 |
369 |

Subscribing and Unsubscribing

370 |

Subscribing to a topic URL consists of four parts that may occur immediately in sequence or have a delay.

371 |
    372 |
  • Subscriber requests a subscription at the hub
  • 373 |
  • The hub validates the subscription with the publisher (OPTIONAL)
  • 374 |
  • The hub confirms the subscription was actually requested by the subscriber
  • 375 |
  • The hub periodically reconfirms the subscription is still active (OPTIONAL)
  • 376 |
377 |

Unsubscribing works in the same way, except with a single parameter changed to indicate the desire to unsubscribe. Also, the Hub will not validate unsubscription requests with the publisher.

378 |
379 |

Subscriber Sends Subscription Request

380 |

Subscription is initiated by the subscriber making an HTTPS or HTTP POST [[!RFC7231]] request to the hub URL. This request MUST have a Content-Type header of application/x-www-form-urlencoded (described in Section 4.10.22.6 [[!HTML5]]), MUST use UTF-8 [[!Encoding]] as the document character encoding, and MUST use the following parameters in its body, formatted accordingly:

381 |
382 |
hub.callback
383 |
REQUIRED. The subscriber's callback URL where content distribution notifications should be delivered. The callback URL SHOULD be an unguessable URL that is unique per subscription. ([[capability-urls]])
384 |
hub.mode
385 |
REQUIRED. The literal string "subscribe" or "unsubscribe", depending on the goal of the request.
386 |
hub.topic
387 |
REQUIRED. The topic URL that the subscriber wishes to subscribe to or unsubscribe from. Note that this MUST be the "self" URL found during the discovery step, which may be different from the URL that was used to make the discovery request.
388 |
hub.lease_seconds
389 |
OPTIONAL. Number of seconds for which the subscriber would like to have the subscription active, given as a positive decimal integer. Hubs MAY choose to respect this value or not, depending on their own policies, and MAY set a default value if the subscriber omits the parameter. This parameter MAY be present for unsubscription requests and MUST be ignored by the hub in that case.
390 |
hub.secret
391 |
OPTIONAL. A subscriber-provided cryptographically random unique secret string that will be used to compute an HMAC digest for authorized content distribution. If not supplied, the HMAC digest will not be present for content distribution requests. This parameter SHOULD only be specified when the request was made over HTTPS [[!RFC2818]]. This parameter MUST be less than 200 bytes in length.
392 |
393 |

Subscribers MAY also include additional HTTP [[!RFC7230]] request parameters, as well as HTTP [[!RFC7230]] Headers if they are required by the hub.

394 |

Hubs MUST ignore additional request parameters they do not understand.

395 |

Hubs MUST allow subscribers to re-request subscriptions that are already activated. Each subsequent request to a hub to subscribe or unsubscribe MUST override the previous subscription state for a specific topic URL and callback URL combination, but only once the action is verified (Section 4.3). If verification fails, the subscription state MUST be left unchanged. This is required so subscribers can renew their subscriptions before the lease seconds period is over without any interruption. The subscriber MAY use a new hub.secret value in a future subscription, and MAY make a new subscription without a hub.secret.

396 |
397 |

Subscription Parameter Details

398 |

The topic and callback URLs MAY use HTTP [[!RFC7230]] or HTTPS [[!RFC2818]] schemes. The topic URL MUST be the one advertised by the publisher in a Self Link Header during the discovery phase. (See Section 3 ). Hubs MAY refuse subscriptions if the topic URL does not correspond to the one advertised by the publisher. The topic URL can otherwise be free-form following the URL spec [[!URL]]. Hubs MUST always decode non-reserved characters for these URL parameters; see section 1.2 on "Percent-encoded bytes" in [[!URL]].

399 |

The callback URL SHOULD be an unguessable unique URL ([[capability-urls]]) and SHOULD use HTTPS [[!RFC7230]]. The callback URL acts as authentication from the hub to the subscriber when confirming subscriptions and delivering the content. Additionally, the callback SHOULD be unique (not re-used for multiple hubs) and changed when subscriptions are renewed.

400 |

The callback URL MAY contain arbitrary query string parameters (e.g., ?foo=bar&red=fish). Hubs MUST preserve the query string during subscription verification by appending new parameters to the end of the list using the & (ampersand) character to join. Existing parameters with names that overlap with those used by verification requests will not be overwritten. When sending the content distribution request, the hub will make a POST request to the callback URL including any query string parameters in the URL portion of the request, not as POST body parameters.

401 |
402 |
403 |

Subscription Response Details

404 |

If the hub URL supports WebSub and is able to handle the subscription or unsubscription request, it MUST respond to a subscription request with an HTTP [[!RFC7231]] 202 "Accepted" response to indicate that the request was received and will now be verified (Section 5.3) and validated (Section 5.2) by the hub. The hub SHOULD perform the verification and validation of intent as soon as possible.

405 |

If a hub finds any errors in the subscription request, an appropriate HTTP [[!RFC7231]] error response code (4xx or 5xx) MUST be returned. In the event of an error, hubs SHOULD return a description of the error in the response body as plain text, used to assist the client developer in understanding the error. This is not meant to be shown to the end user. Hubs MAY decide to reject some callback URLs or topic URLs based on their own policies (e.g., domain authorization, topic URL port numbers). However, since verification and validation of intent are asynchronous steps that logically begin after the HTTP response has been returned, the HTTP response MUST NOT depend on the process or outcome of verification or validation.

406 |

If the hub URL is not able to handle subscription or unsubscription requests, it MAY redirect to another hub which supports WebSub. It does so by yielding an HTTP [[!RFC7231]] 307 (temporary redirect) or 308 (permanent redirect) response. It MUST also include at least a HTTP [[!RFC7230]] Location Header containing a preferred URL reference for the hub to use by the subscriber. The subscriber is expected to retry the subscription or unsubscription at the new hub URL.

407 |
408 |
409 |
410 |

Subscription Validation

411 |

Subscriptions MAY be validated by the Hubs who may require more details to accept or refuse a subscription. The Hub MAY also check with the publisher whether the subscription should be accepted.

412 |

If (and when) the subscription is accepted, the hub MUST perform the verification of intent of the subscriber.

413 |

If (and when) the subscription is denied, the hub MUST inform the subscriber by sending an HTTP [[!RFC7231]] (or HTTPS [[!RFC2818]]) GET request to the subscriber's callback URL as given in the subscription request. This request has the following query string arguments appended (format described in Section 4 of [[!URL]]):

414 |
415 |
hub.mode
416 |
REQUIRED. The literal string "denied".
417 |
hub.topic
418 |
REQUIRED. The topic URL given in the corresponding subscription request.
419 |
hub.reason
420 |
OPTIONAL. The hub may include a reason for which the subscription has been denied.
421 |
422 |

The subscription MAY be denied by the hub at any point (even if it was previously accepted). The Subscriber SHOULD then consider that the subscription is not possible anymore.

423 |
424 |
425 |

Hub Verifies Intent of the Subscriber

426 |

In order to prevent an attacker from creating unwanted subscriptions on behalf of a subscriber (or unsubscribing desired ones), a hub must ensure that the subscriber did indeed send the subscription request.

427 |

The hub verifies a subscription request by sending an HTTP [[!RFC7231]] (or HTTPS [[!RFC2818]]) GET request to the subscriber's callback URL as given in the subscription request. This request has the following query string arguments appended (format described in Section 4 of [[!URL]]):

428 |
429 |
hub.mode
430 |
REQUIRED. The literal string "subscribe" or "unsubscribe", which matches the original request to the hub from the subscriber.
431 |
hub.topic
432 |
REQUIRED. The topic URL given in the corresponding subscription request.
433 |
hub.challenge
434 |
REQUIRED. A hub-generated, random string that MUST be echoed by the subscriber to verify the subscription.
435 |
hub.lease_seconds
436 |
REQUIRED/OPTIONAL. The hub-determined number of seconds that the subscription will stay active before expiring, measured from the time the verification request was made from the hub to the subscriber. Hubs MUST supply this parameter when hub.mode is set to "subscribe". This parameter MAY be present when hub.mode is "unsubscribe" and MUST be ignored by subscribers in that case.
437 |
438 |
439 |

Verification Details

440 |

The subscriber MUST confirm that the hub.topic corresponds to a pending subscription or unsubscription that it wishes to carry out. If so, the subscriber MUST respond with an HTTP success (2xx) code with a response body equal to the hub.challenge parameter. If the subscriber does not agree with the action, the subscriber MUST respond with a 404 "Not Found" response.

441 |

The hub MUST consider other server response codes (3xx, 4xx, 5xx) to mean that the verification request has failed. If the subscriber returns an HTTP [[!RFC7231]] success (2xx) but the content body does not match the hub.challenge parameter, the hub MUST also consider verification to have failed.

442 |

Hubs MAY make the hub.lease_seconds equal to the value the subscriber passed in their subscription request but MAY change the value depending on the hub's policies. To sustain a subscription, the subscriber MUST re-request the subscription on the hub before hub.lease_seconds seconds has elapsed.

443 |

Hubs MUST enforce lease expirations, and MUST NOT issue perpetual lease durations.

444 |
445 |
446 |

The spec uses GET vs POST to differentiate between the confirmation/denial of the subscription request and delivering the content. While this is not considered "best practice" from a web architecture perspective, it does make implementation of the callback URL simpler. Since the POST body of the content distribution request may be any arbitrary content type and only includes the actual content of the document, using the GET vs POST distinction to switch between handling these two modes makes implementations simpler.

447 |
448 | 449 |
450 |

Publishing

451 |

The publisher MUST inform the hubs it previously designated when a topic has been updated. The hub and the publisher can agree on any mechanism, as long as the hub is eventually able send the updated payload to the subscribers.

452 | 453 |

The specific mechanism for the publisher to inform the hub is left unspecified. For example, some existing public hubs [1] [2] [3] ask publishers to send a POST request with the keys hub.mode="publish" and hub.url=(the URL of the resource that was updated).

454 | 455 |
456 |

Subscription Migration

457 |

If the publisher wishes to migrate existing subscriptions to a new topic URL, it can do so using HTTP redirects.

458 |
    459 |
  • The previous topic URL should send a redirect to the new topic URL. This will provide a seamless transition for any HTTP client that did not use WebSub but instead was polling the topic URL.
  • 460 |
  • When existing WebSub subscriptions expire, subscribers will attempt to renew the subscription. The first step of renewing a subscription is to fetch the topic URL, which means the subscriber will encounter the redirect and end up at the new topic URL.
  • 461 |
  • At the new topic URL, the subscriber will see the new rel=self URL and the new hub, and will subscribe to the new topic URL at the new hub.
  • 462 |
463 |

This does not require any participation on the part of the previous hub, and works whether or not the publisher changes hubs as well.

464 |
465 |
466 | 467 |
468 |

Content Distribution

469 |

A content distribution request is sent from the Hub to the Subscriber when new content is available for a topic URL. The request is an HTTP [[!RFC7231]] (or HTTPS [[!RFC2818]]) POST request from the hub to the subscriber's callback URL. The HTTP body of the POST request MUST include the payload of the content distribution notification. The content distribution request MUST have a Content-Type Header corresponding to the Content-Type of the topic, and MUST contain the full contents of the topic URL, with an exception allowed as described below. 470 |

471 |

For Atom ([[RFC4287]]) and RSS ([[RSS-2.0]]) feeds, the hub MAY remove already-delivered atom:entry or rss:item elements from the feed. 472 |

473 |

The request MUST include at least one Link Header [[!RFC5988]] with rel=hub pointing to a Hub associated with the topic being updated. It MUST also include one Link Header [[!RFC5988]] with rel=self set to the canonical URL of the topic being updated. The Hub SHOULD combine these headers into a single Link Header [[!RFC5988]]. All these URLs are those resulting from the discovery process (Section 3). The subscriber MUST NOT use these Link headers to identify the subscription corresponding to the content distribution request, because the Link headers are metadata associated with the topic content, not with any particular subscription. For example, the topic URL in the content distribution request may be different from the topic URL that was originally subscribed to. 474 |

475 |

The subscriber's callback URL MUST return an HTTP [[!RFC7231]] 2xx response code to indicate a success. The subscriber's callback URL MAY return an HTTP 410 code to indicate that the subscription has been deleted, and the hub MAY terminate the subscription if it receives that code as a response. The hub MUST consider all other subscriber response codes as failures; that means subscribers MUST NOT use HTTP redirects for moving subscriptions. Subscribers SHOULD respond to content distribution requests as quickly as possible; their success response code SHOULD only indicate receipt of the message, not acknowledgment that it was successfully processed by the subscriber. The response body from the subscriber MUST be ignored by the hub. Hubs SHOULD retry content distribution requests up to self-imposed limits on the number of times and the overall time period to retry. When the failing delivery exceeds the hub's limits, the hub stops attempting to deliver that nofication. The hub MUST keep the subscription active until the end of the lease duration, and if a new update is published to the topic, MUST continue to retry delivery to the previously-failing subscriber. 476 |

477 |
478 |

Authenticated Content Distribution

479 |

If the subscriber supplied a value for hub.secret in their subscription request, the hub MUST generate an HMAC signature of the payload and include that signature in the request headers of the content distribution request. The X-Hub-Signature header's value MUST be in the form method=signature where method is one of the recognized algorithm names and signature is the hexadecimal representation of the signature. The signature MUST be computed using the HMAC algorithm [[!RFC6151]] with the request body as the data and the hub.secret as the key.

480 | 481 |
482 |

Recognized algorithm names

483 | 484 |

The following algorithms are the initially registered algorithm names, based on the contents of the [[FIPS-PUB-180-4]] registry at the time of publishing.

485 |
486 |
sha1
487 |
The SHA-1 algorithm as specified in Section 6.1 of [[FIPS-PUB-180-4]]
488 |
sha256
489 |
The SHA-256 algorithm as specified in Section 6.2 of [[FIPS-PUB-180-4]]
490 |
sha384
491 |
The SHA-384 algorithm as specified in Section 6.5 of [[FIPS-PUB-180-4]]
492 |
sha512
493 |
The SHA-512 algorithm as specified in Section 6.4 of [[FIPS-PUB-180-4]]
494 |
495 |

In the future, an extension may be specified allowing subscribers to indicate which algorithms they can use for validation. As of this writing, most hubs sign with SHA-1, despite its known cryptographic weakness, in order to be interoperable with older subscribers.

496 |
497 | 498 |
499 |

Signature validation

500 |

When subscribers receive a content distribution request with the X-Hub-Signature header specified, they SHOULD recompute the signature with the shared secret using the same method (provided in the X-Hub-Signature header) as the hub. If the signature does not match, subscribers MUST locally ignore the message as invalid. Subscribers MAY still acknowledge this request with a 2xx response code in order to be able to process the message asynchronously and/or prevent brute-force attempts of the signature. Using this technique along with HTTPS [[!RFC2818]] for subscription requests enables simple subscribers to receive authenticated content distribution requests from hubs without the need for subscribers to run an HTTPS [[!RFC2818]] server.

501 |

Please note however that this signature only ensures that the payload was not forged. Since the request also includes headers, these should not be considered as safe by the subscriber, unless of course the subscriber uses HTTPS [[!RFC2818]] callbacks.

502 |
503 |
504 |
505 | 506 |
507 |

Security Considerations

508 |

Here is a summary of security considerations. It is important to note that WebSub is a server-to-server protocol which relies only on HTTP. It is strongly recommended to use HTTPS for all requests.

509 |
510 |

Discovery

511 |

The decision about whether a subscriber should look for <link> elements inside a page's <body> (as well as the <head>) is not straightforward, and there is currently no clear consensus. One reason to ignore the <body> during discovery is that some web sites might (perhaps accidentally) allow users to post content containing <link> elements, though the working group does not know of any specific examples of such sites. If WebSub discovery uses such <link> elements, a user contributing to such sites could potentially maliciously cause all subscribers to use an alternate hub which later delivers malicious content. Given this potential attack, it may be prudent to do discovery only in the <head> of HTML documents.

512 |
513 |
514 |

Subscriptions

515 |

First, subscribers SHOULD always favor the HTTPS URL for hubs (even if the URL is advertised as HTTP). Second, subscribers SHOULD use unique unguessable capability URLs for the callbacks, as well as make them available via HTTPS. Finally, subscribers SHOULD use a hub.secret when subscribing to allow signature of the content distribution.

516 |

Hubs SHOULD enforce short lived hub.lease_seconds (10 days is a good default). When performing intent verification, the hub SHOULD use a random, single-use hub.challenge.

517 |
518 |
519 |

Distribution

520 |

The Hub MUST use the exact callback used by the subscriber (including the use of HTTPS). Hubs MUST sign their requests using the hub.secret supplied by subscribers if requested.

521 |

If the subscriber included a hub.secret in the subscription request, the subscriber SHOULD validate the hub's provided signature, and if they do so, they MUST use the server's stated signature mechanism, and discard requests which fail the test.

522 |

If a subscriber does not use a secure callback URL (HTTPS), or if it is suspected that the TLS transport between the hub and subscriber may be compromised, then the integrity of the content delivery notification is only protected by the hub.secret and the hashing algorithm used. In this case, an appropriate hashing algorithm should be used based on the security requirements of the application. As SHA-1 has been demonstrated to be compromised as of the date of this publication, a minimum of SHA-256 should be used.

523 |
524 |
525 |

Security and Privacy Review

526 |

These questions provide an overview of security and privacy considerations for this specification as guided by Self-Review Questionnaire: Security and Privacy ([[security-privacy-questionnaire]]).

527 | 528 |
529 |
Does this specification deal with personally-identifiable information?
530 |
The only potentially personally-identifiable information involved are topic and callback URLs.
531 |
Does this specification deal with high-value data?
532 |
No, there is no authentication or other credentials involved.
533 |
Does this specification introduce new state for an origin that persists across browsing sessions?
534 |
No.
535 |
Does this specification expose persistent, cross-origin state to the web?
536 |
The WebSub subscriber should create a resource with information about the topic to which it subscribes.
537 |
Does this specification expose any other data to an origin that it doesn't currently have access to?
538 |
No.
539 |
Does this specification enable new script execution/loading mechanisms?
540 |
No.
541 |
Does this specification allow an origin access to a user's location?
542 |
No.
543 |
Does this specification allow an origin access to sensors on a user's device?
544 |
No.
545 |
Does this specification allow an origin access to aspects of a user's local computing environment?
546 |
No.
547 |
Does this specification allow an origin access to other devices?
548 |
No.
549 |
Does this specification allow an origin some measure of control over a user agent's native UI?
550 |
No.
551 |
Does this specification expose temporary identifiers to the web?
552 |
No.
553 |
Does this specification distinguish between behavior in first-party and third-party contexts?
554 |
No.
555 |
How should this specification work in the context of a user agent's "incognito" mode?
556 |
WebSub is a server to server protocol, in which "incognito" mode does not have a meaning.
557 |
Does this specification persist data to a user's local device?
558 |
No.
559 |
Does this specification allow downgrading default security characteristics?
560 |
No.
561 |
562 |
563 |
564 | 565 |
566 |

Acknowledgements

567 | 568 |

The editors wish to thank the authors of PubSubHubbub, the IndieWeb community, and other implementers for their support, encouragement and enthusiasm. In particular, the editors wish to thank 569 | Brad Fitzpatrick, 570 | Brett Slatkin, 571 | Martin Atkins, 572 | Amy Guy, 573 | Barry Frost, 574 | Benjamin Roberts, 575 | Eugen Rochko, 576 | Jordan Potter, 577 | Matthias Pfefferle, 578 | Malcolm Blaney, 579 | Marten de Vries, 580 | Sandro Hawke, 581 | Tantek Çelik, 582 | and 583 | Tony Garnock-Jones. 584 |

585 | 586 |
587 |

Change Log

588 | 589 |
590 |

Changes from 03 October 2017 PR to this version

591 | 592 |
    593 |
  • Added link to content negotiation section from corresponding item in conformance criteria
  • 594 |
  • Updated reference name from "WHATWG-URL" to "[[URL]]", but does not change the actual reference.
  • 595 |
  • Rephrase sentence on hub URL discovery to better clarify which URLs are being talked about, and use "notify" instead of "ping"
  • 596 |
  • Correct "mime-type" to "Media Type" and add informative reference to RFC.
  • 597 |
  • Rephrase summary of "subscribing and unsubscribing" to explicitly mention the actor of each step
  • 598 |
  • Clarify sending the POST request to the subscriber's callback URL
  • 599 |
  • Add reference to HTTPS when previously only HTTP was mentioned in cases where an HTTPS URL may be used
  • 600 |
  • Clarify when hub.lease_seconds parameter is required or optional
  • 601 |
  • Reword section on subscription migration to make it more clear
  • 602 |
  • Move note about publisher->hub notification outside of the subscription migration section
  • 603 |
  • Remove references to "notification" as a standalone term, replaced by "content distribution request" or "content distribution notification" as appropriate
  • 604 |
  • Update CR exit criteria text to past tense
  • 605 |
  • Added explanatory text about why a publisher may advertise multiple hubs
  • 606 |
  • Replaced sentence in section 8 to better describe the situation "the topic URL in the content distribution request may be different from the topic URL that was originally subscribed to"
  • 607 |
  • Dropped at-risk limitation of the link tag in the head
  • 608 |
  • Added security consideration for discovery related to link rel discovery in body vs head
  • 609 |
  • Dropped unused feature of the hub rejecting the subscription and providing an alternate topic URL
  • 610 |
  • Added sequence diagram in high-level overview section, and minor updates to phrasing of that section
  • 611 |
  • Added acknowledgements
  • 612 |
  • Note that hubs may set a default value for lease_seconds
  • 613 |
614 |
615 | 616 |
617 |

Changes from 11 April 2017 CR to 03 October 2017 PR

618 | 619 |
    620 |
  • Adds informative guidelines for how publishers can migrate subscribers to a new topic URL
  • 621 |
  • Allow subscribers to reject invalid signatures with response codes other than 2xx
  • 622 |
  • Suggest subscribers return HTTP 410 if a subscription has been deleted
  • 623 |
  • Add informative note about the lack of specification of publisher-hub relationship
  • 624 |
  • Drop at-risk .host-meta discovery feature due to lack of implementations (Issue #97)
  • 625 |
  • Add text to note the subscriber's hub.secret should be cryptographically random and unique
  • 626 |
  • Clarify that failed delivery of notifications should not delete the subscription before the lease duration ends (Issue #119)
  • 627 |
  • Replaced note about referring to FIPS document for algorithm extensions with a note that says a proper WebSub extension should be defined in the future that enables negotiation of the hashing algorithm between subscribers and hubs
  • 628 |
  • Add example of returning a different rel=self URL depending on the HTTP Accept-Language header
  • 629 |
  • Add a note in Security Considerations about the hashing algorithm protecting against a compromised TLS channel
  • 630 |
  • Clarify security consideration section regarding signature validation
  • 631 |
  • Moved "at risk" section out of the "sotd" section which was causing a respec error
  • 632 |
  • Replaced hyperlink to FIPS PUB 180-4 with an in-page reference
  • 633 |
634 |
635 | 636 |
637 |

Changes from 24 November WD to 11 April 2017 CR

638 | 639 |
    640 |
  • Clarified wording on supported algorithms for authenticated distribution
  • 641 |
  • Only allow <link> tags in the HTML <head> element
  • 642 |
  • Added conformance criteria and CR exit criteria
  • 643 |
  • Added examples of discovery request and response
  • 644 |
  • Added example of using different rel=self URLs to support content negotiation
  • 645 |
  • Added a security considerations section
  • 646 |
  • Updated references to WHATWG-URL instead of HTML 4
  • 647 |
  • Replaced abstract with updated description
  • 648 |
649 |
650 | 651 |
652 |

Changes from 20 October FPWD to 24 November 2016

653 | 654 |
    655 |
  • Added informative reference to previous versions of the spec, PubSubHubbub 0.3 and 0.4
  • 656 |
  • Split discovery section into separate publisher and subscriber sections
  • 657 |
  • Clarify that publishers can use any available discovery method, and subscribers must support all
  • 658 |
  • Marked host-meta discovery method At Risk due to no known implementations, and fixed reference to Host Meta spec instead of the previous reference to Well-Known
  • 659 |
  • Recommend using Capability URLs as the subscriber's callback URLs for security and authenticating the notification delivery
  • 660 |
  • Recommend not reusing callback URLs on subscription renewals
  • 661 |
  • Clarify that the hub.topic must be the self URL that was discovered
  • 662 |
  • Dropped the recommendation of including the From header on subscription requests
  • 663 |
  • Clarify that the hub response to subscription requests must not depend on the verification or validation
  • 664 |
  • Hubs must enforce lease expirations
  • 665 |
  • Clarify that the notification payload should contain the full contents of the topic URL
  • 666 |
  • Recommend that hubs should retry failed notification delivery up to self-imposed limits
  • 667 |
  • Clarify that future defined signature methods in FIPS PUB 180-4 are allowed
  • 668 |
  • Added informative note about the use of GET vs POST at the callback URL
  • 669 |
  • Renamed the spec to WebSub
  • 670 |
671 |
672 | 673 |
674 | 675 | 691 | 692 | 693 | -------------------------------------------------------------------------------- /staged/fpwd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 108 | 378 | 379 | PubSub 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 466 | 467 | 468 | 469 | 526 | 527 |
528 |

Abstract

529 |

An open, simple, web-scale and decentralized pubsub protocol. Anybody can play.

530 |

As opposed to more developed (and more complex) pubsub specs like Jabber Publish-Subscribe [XEP-0060] this spec's base profile (the barrier-to-entry to speak it) is dead simple. The fancy bits required for high-volume publishers and subscribers are optional. The base profile is HTTP-based, as opposed to XMPP (see more on this below).

531 |

To dramatically simplify this spec in several places where we had to choose between supporting A or B, we took it upon ourselves to say "only A", rather than making it an implementation decision.

532 |

We offer this spec in hopes that it fills a need or at least advances the state of the discussion in the pubsub space. Polling is extremely wasteful and high latency. We think a decentralized pubsub layer is a fundamental, missing layer in the Internet architecture today and its existence, more than just enabling the obvious lower latency feed readers, would enable many cool applications, most of which we can't even imagine. But we're looking forward to decentralized social networking.

533 |
534 | 535 |
536 |

Status of This Document

537 |

538 | This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/. 539 |

540 | 541 |

542 | This document is currently an editor's draft. Current bugs and issues are managed in GitHub. 543 |

544 | 545 |

546 | This document was published by the Social Web Working Group as a First Public Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to 547 | public-socialweb@w3.org (subscribe, 548 | archives). All comments are welcome. 549 |

550 |

551 | Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress. 552 |

553 |

554 | This document was produced by a group operating under the 555 | 5 February 2004 W3C Patent 556 | Policy. 557 | W3C maintains a public list of any patent 558 | disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains 559 | Essential 560 | Claim(s) must disclose the information in accordance with 561 | section 562 | 6 of the W3C Patent Policy. 563 |

564 |

This document is governed by the 1 September 2015 W3C Process Document. 565 |

566 | 567 |
568 | 608 | 609 | 610 | 611 |
612 | 613 |

1. Definitions 614 |

615 |
616 |
Topic
617 |
An HTTP [RFC7230] resource URL. The unit to which one can subscribe to changes.
618 |
Hub ("the hub")
619 |
The server (URL [RFC3986]) which implements both sides of this protocol. Any hub MAY implement its own policies on who can use it.
620 |
Publisher
621 |
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".
622 |
Subscriber
623 |
An entity (person or program) that wants to be notified of changes on a topic. The subscriber must be directly network-accessible and is identified by its Subscriber Callback URL.
624 |
Subscription
625 |
A unique relation to a topic by a subscriber that indicates it should receive updates for that topic. A subscription's unique key is the tuple (Topic URL, Subscriber Callback URL). Subscriptions may (at the hub's decision) have expiration times akin to DHCP leases which must be periodically renewed.
626 |
Subscriber Callback URL
627 |
The URL [RFC3986] at which a subscriber wishes to receive notifications.
628 |
Event
629 |
An event that causes updates to multiple topics. For each event that happens (e.g. "Brad posted to the Linux Community."), multiple topics could be affected (e.g. "Brad posted." and "Linux community has new post"). Publisher events cause topics to be updated and the hub looks up all subscriptions for affected topics, sending out notifications to subscribers.
630 |
Notification
631 |
A payload describing how a topic's contents have changed, or the full updated content. Depending on the topic's content type, the difference (or "delta") may be computed by the hub and sent to all subscribers.
632 |
633 |
634 | 635 |
636 | 637 |

2. High-level protocol flow 638 |

639 |

(This section is non-normative.)

640 |
    641 |
  • Publishers notify their hub(s) URLs when their topic(s) change.
  • 642 |
  • Subscribers POST to one or more of the advertised hubs for a topic they're interested in. Alternatively, some hubs may offer auto-polling capability, to let subscribers subscribe to topics which don't advertise a hub.
  • 643 |
  • The hub caches minimal metadata (id, data, entry digest) about each topic's previous state. When the hub re-fetches a topic feed (on its own initiative or as a result of a publisher's ping) and finds a delta, it enqueues a notification to all registered subscribers.
  • 644 |
645 |
646 | 647 |
648 | 649 |

3. Discovery 650 |

651 |

A potential subscriber initiates discovery by retrieving (GET or HEAD request) the topic to which it wants to subscribe. The HTTP [RFC7231] response from the publisher MUST include at least one Link Header [RFC5988] with rel=hub (a hub link header) as well as exactly one Link Header [RFC5988] with rel=self (the self link header). The former MUST indicate the exact URL of a PubSub hub designated by the publisher. If more than one URL is specified, it is expected that the publisher pings each of these URLs, so the subscriber may subscribe to one or more of these. The latter will point to the permanent URL for the resource being polled.

652 |

In the absence of HTTP [RFC7231] Link headers, subscribers MAY fall back to other methods to discover the hub(s) and the canonical URI of the topic. If the topic is an XML based feed, it MAY use embedded link elements as described in Appendix B of Web Linking [RFC5988]. Similarly, for HTML pages, it MAY use embedded link elements as described in Appendix A of Web Linking [RFC5988]. Finally, publishers MAY also use the Well-Known Uniform Resource Identifiers [RFC5785] .host-meta to include the <Link> element with rel="hub".

653 |
654 | 655 |
656 | 657 |

4. Subscribing and Unsubscribing 658 |

659 |

Subscribing to a topic URL consists of four parts that may occur immediately in sequence or have a delay.

660 |
    661 |
  • Requesting a subscription using the hub
  • 662 |
  • Validating the subscription with the publisher (OPTIONAL)
  • 663 |
  • Confirming the subscription was actually desired by the subscriber
  • 664 |
  • Periodically reconfirming the subscription is still active (OPTIONAL)
  • 665 |
666 |

Unsubscribing works in the same way, except with a single parameter changed to indicate the desire to unsubscribe. Also, the Hub will not validate unsubscription requests with the publisher.

667 | 668 |
669 |

4.1 Subscriber Sends Subscription Request 670 |

671 |

Subscription is initiated by the subscriber making an HTTPS or HTTP POST [RFC7231] request to the hub URL. This request has a Content-Type of application/x-www-form-urlencoded (described in Section 17.13.4 of [W3C.REC-html401-19991224]) and the following parameters in its body:

672 |
673 |
hub.callback
674 |
REQUIRED. The subscriber's callback URL where notifications should be delivered. It is considered good practice to use a unique callback URL for each subscription.
675 |
hub.mode
676 |
REQUIRED. The literal string "subscribe" or "unsubscribe", depending on the goal of the request.
677 |
hub.topic
678 |
REQUIRED. The topic URL that the subscriber wishes to subscribe to or unsubscribe from.
679 |
hub.lease_seconds
680 |
OPTIONAL. Number of seconds for which the subscriber would like to have the subscription active. Hubs MAY choose to respect this value or not, depending on their own policies. This parameter MAY be present for unsubscription requests and MUST be ignored by the hub in that case.
681 |
hub.secret
682 |
OPTIONAL. A subscriber-provided secret string that will be used to compute an HMAC digest for authorized content distribution. If not supplied, the HMAC digest will not be present for content distribution requests. This parameter SHOULD only be specified when the request was made over HTTPS [RFC2818]. This parameter MUST be less than 200 bytes in length.
683 |
684 |

Subscribers MAY also include additional HTTP [RFC7230] request parameters, as well as HTTP [RFC7230] Headers if they are required by the hub. In the context of social web applications, it is considered good practice to include a From HTTP [RFC7231] header (as described in section 5.5.1 of Hypertext Transfer Protocol [RFC7231]) to indicate on behalf of which user the subscription is being performed.

685 |

Hubs MUST ignore additional request parameters they do not understand.

686 |

Hubs MUST allow subscribers to re-request subscriptions that are already activated. Each subsequent request to a hub to subscribe or unsubscribe MUST override the previous subscription state for a specific topic URL and callback URL combination once the action is verified. Any failures to confirm the subscription action MUST leave the subscription state unchanged. This is required so subscribers can renew their subscriptions before the lease seconds period is over without any interruption.

687 | 688 |
689 |

4.1.1 Subscription Parameter Details 690 |

691 |

The topic and callback URLs MAY use HTTP or HTTPS [RFC7230] schemes. The topic URL MUST be the one advertised by the publisher in a Self Link Header during the discovery phase. (See Section 4 ). Hubs MAY refuse subscriptions if the topic URL does not correspond to the one advertised by the publisher. The topic URL can otherwise be free-form following the URI spec [RFC3986]. Hubs MUST always decode non-reserved characters for these URL parameters; see section 2.4 on "When to Encode or Decode" in the URI spec [RFC3986].

692 |

The callback URL MAY contain arbitrary query string parameters (e.g., ?foo=bar&red=fish). Hubs MUST preserve the query string during subscription verification by appending new parameters to the end of the list using the & (ampersand) character to join. Existing parameters with names that overlap with those used by verification requests will not be overwritten. For event notification, the callback URL will be POSTed to including any query-string parameters in the URL portion of the request, not as POST body parameters.

693 |
694 | 695 |
696 |

4.1.2 Subscription Response Details 697 |

698 |

The hub MUST respond to a subscription request with an HTTP [RFC7231] 202 "Accepted" response to indicate that the request was received and will now be verified (Section 5.3 ) and validated (Section 5.2 ) by the hub. The hub SHOULD perform the verification and validation of intent as soon as possible.

699 |

If a hub finds any errors in the subscription request, an appropriate HTTP [RFC7231] error response code (4xx or 5xx) MUST be returned. In the event of an error, hubs SHOULD return a description of the error in the response body as plain text. Hubs MAY decide to reject some callback URLs or topic URLs based on their own policies (e.g., domain authorization, topic URL port numbers).

700 |
701 |
702 | 703 |
704 |

4.2 Subscription Validation 705 |

706 |

Subscriptions MAY be validated by the Hubs who may require more details to accept or refuse a subscription. The Hub MAY also check with the publisher whether the subscription should be accepted.

707 |

If (and when), the subscription is accepted, the hub MUST perform the verification of intent of the subscriber.

708 |

If (and when), the subscription is denied, the hub MUST inform the subscriber by sending an HTTP [RFC7231] GET request to the subscriber's callback URL as given in the subscription request. This request has the following query string arguments appended (format described in Section 17.13.4 of [W3C.REC-html401-19991224]):

709 |
710 |
hub.mode
711 |
REQUIRED. The literal string "denied".
712 |
hub.topic
713 |
REQUIRED. The topic URL given in the corresponding subscription request.
714 |
hub.reason
715 |
OPTIONAL. The hub may include a reason for which the subscription has been denied.
716 |
717 |

Hubs may provide an additional HTTP [RFC7231] Location header (as described in section 7.1.2 of Hypertext Transfer Protocol [RFC7231]) to indicate that the subscriber may retry subscribing to a different hub.topic. This allows for limited distribution to specific groups or users in the context of social web applications.

718 |

The subscription MAY be denied by the hub at any point (even if it was previously accepted). The Subscriber SHOULD then consider that the subscription is not possible anymore.

719 |
720 | 721 |
722 |

4.3 Hub Verifies Intent of the Subscriber 723 |

724 |

In order to prevent an attacker from creating unwanted subscriptions on behalf of a subscriber (or unsubscribing desired ones), a hub must ensure that the subscriber did indeed send the subscription request.

725 |

The hub verifies a subscription request by sending an HTTP [RFC7231] GET request to the subscriber's callback URL as given in the subscription request. This request has the following query string arguments appended (format described in Section 17.13.4 of [W3C.REC-html401-19991224]):

726 |
727 |
hub.mode
728 |
REQUIRED. The literal string "subscribe" or "unsubscribe", which matches the original request to the hub from the subscriber.
729 |
hub.topic
730 |
REQUIRED. The topic URL given in the corresponding subscription request.
731 |
hub.challenge
732 |
REQUIRED. A hub-generated, random string that MUST be echoed by the subscriber to verify the subscription.
733 |
hub.lease_seconds
734 |
REQUIRED/OPTIONAL. The hub-determined number of seconds that the subscription will stay active before expiring, measured from the time the verification request was made from the hub to the subscriber. Hubs MUST supply this parameter for subscription requests. This parameter MAY be present for unsubscribe requests and MUST be ignored by subscribers during unsubscription.
735 |
736 | 737 |
738 |

4.3.1 Verification Details 739 |

740 |

The subscriber MUST confirm that the hub.topic corresponds to a pending subscription or unsubscription that it wishes to carry out. If so, the subscriber MUST respond with an HTTP success (2xx) code with a response body equal to the hub.challenge parameter. If the subscriber does not agree with the action, the subscriber MUST respond with a 404 "Not Found" response.

741 |

The hub MUST consider other server response codes (3xx, 4xx, 5xx) to mean that the verification request has failed. If the subscriber returns an HTTP [RFC7231] success (2xx) but the content body does not match the hub.challenge parameter, the hub MUST also consider verification to have failed.

742 |

Hubs MAY make the hub.lease_seconds equal to the value the subscriber passed in their subscription request but MAY change the value depending on the hub's policies. To sustain a subscription, the subscriber MUST re-request the subscription on the hub before hub.lease_seconds seconds has elapsed.

743 |
744 |
745 |
746 | 747 |
748 | 749 |

5. Publishing 750 |

751 |

The publisher MUST inform the hubs it previously designated when a topic has been updated. The hub and the publisher can agree on any mechanism, as long as the hub is eventually able send the updated payload to the subscribers.

752 |
753 | 754 |
755 | 756 |

6. Content Distribution 757 |

758 |

A content distribution request is an HTTP [RFC7231] POST request from hub to the subscriber's callback URL with the payload of the notification. This request MUST have a Content-Type corresponding to the media type of the topic. The hub MAY reduce the payload to a diff between two consecutive versions if its format allows it. 759 |

760 |

The request MUST include a Link Header [RFC5988] with rel=hub pointing to the Hub as well as a Link Header [RFC5988] with rel=self set to the topic that's being updated. The Hub SHOULD combine both headers into a single Link Header [RFC5988]. 761 |

762 |

The successful response from the subscriber's callback URL MUST be an HTTP [RFC7231] success (2xx) code. The hub MUST consider all other subscriber response codes as failures; that means subscribers MUST NOT use HTTP redirects for moving subscriptions. The response body from the subscriber MUST be ignored by the hub. Hubs SHOULD retry notifications repeatedly until successful (up to some reasonable maximum over a reasonable time period). Subscribers SHOULD respond to notifications as quickly as possible; their success response code SHOULD only indicate receipt of the message, not acknowledgment that it was successfully processed by the subscriber. 763 |

764 | 765 |
766 |

6.1 Authenticated Content Distribution 767 |

768 | 769 |
770 |

If the subscriber supplied a value for hub.secret in their subscription request, the hub MUST generate an HMAC signature of the payload and include that signature in the request headers of the content distribution request. The X-Hub-Signature header's value MUST be in the form method=signature where method is one of the recognized algorithm names and signature is the, hexadecimal representation of the signature. The signature MUST be computed using the HMAC algorithm [RFC6151] with the request body as the data and the hub.secret as the key.

771 |
772 | 773 |
774 |

6.1.1 Recognized algorithm names 775 |

776 | 777 |

The following algorithms are currently added as recognized algorithm names, as specified by [FIPS PUB 180-4]:

778 |
779 |
sha1
780 |
The SHA-1 algorithm as specified in Section 6.1 of [FIPS PUB 180-4]
781 |
sha256
782 |
The SHA-256 algorithm as specified in Section 6.2
783 |
sha384
784 |
The SHA-384 algorithm as specified in Section 6.5
785 |
sha512
786 |
The SHA-512 algorithm as specified in Section 6.4
787 |
788 |

In the future, any algorithm added to [FIPS PUB 180-4] SHOULD be supported by hubs and subscribers.

789 |
790 | 791 |
792 |

6.1.2 Signature validation 793 |

794 |

When subscribers receive a content distribution request with theX-Hub-Signature header specified, they SHOULD recompute the signature with the shared secret using the same method (provided in the X-Hub-Signature header) as the hub. If the signature does not match, subscribers MUST still return a 2xx success response to acknowledge receipt, but locally ignore the message as invalid. Using this technique along with HTTPS [RFC2818] for subscription requests enables simple subscribers to receive authenticated notifications from hubs without the need for subscribers to run an HTTPS [RFC2818] server.

795 |

Please note however that this signature only ensures that the payload was not forged. Since the notification also includes headers, these should not be considered as safe by the subscriber, unless of course the subscriber uses HTTPS [RFC2818] callbacks.

796 |
797 | 798 |
799 | 800 | 801 |
802 | 803 | 804 | 805 | 806 |
807 | 808 |

A. References 809 |

810 | 811 |
812 |

A.1 Normative references 813 |

814 |
[RFC2818]
815 |
E. Rescorla. IETF. HTTP Over TLS. May 2000. Informational. URL: https://tools.ietf.org/html/rfc2818 816 |
[RFC3986]
817 |
T. Berners-Lee; R. Fielding; L. Masinter. IETF. Uniform Resource Identifier (URI): Generic Syntax. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986 818 |
[RFC5785]
819 |
M. Nottingham; E. Hammer-Lahav. IETF. Defining Well-Known Uniform Resource Identifiers (URIs). April 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5785 820 |
[RFC5988]
821 |
M. Nottingham. IETF. Web Linking. October 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5988 822 |
[RFC6151]
823 |
S. Turner; L. Chen. IETF. Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms. March 2011. Informational. URL: https://tools.ietf.org/html/rfc6151 824 |
[RFC7230]
825 |
R. Fielding, Ed.; J. Reschke, Ed.. IETF. Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing. June 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7230 826 |
[RFC7231]
827 |
R. Fielding, Ed.; J. Reschke, Ed.. IETF. Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. June 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7231 828 |
[W3C.REC-html401-19991224]
829 |
Dave Raggett; Arnaud Le Hors; Ian Jacobs. W3C. HTML 4.01 Specification. W3C Recommendation. URL: https://www.w3.org/TR/1999/REC-html401-19991224/ 830 |
[XEP-0060]
831 |
Peter Millard; Peter Saint-Andre; Ralph Meijer. XMPP Standards Foundation. Publish-Subscribe. Draft. URL: http://www.xmpp.org/extensions/xep-0060.html 832 |
833 |
834 |
835 |
836 | 837 | 838 | 839 | 840 | -------------------------------------------------------------------------------- /staged/rec/manifest.txt: -------------------------------------------------------------------------------- 1 | index.html 2 | websub-overview.svg 3 | -------------------------------------------------------------------------------- /staged/rec/websub-overview.svg: -------------------------------------------------------------------------------- 1 | WebSub Flow Diagram Subscriber Publisher Hub Subscriber discovers the hub advertised by publisher's topic Subscriber makes a POST to the hub to subscribe to updates about topic Hub verifies the subscription attempt with a GET Publisher notifies the hub of new content Hub delivers the contents of topicto each subscriber with a POST 2 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": 72531, 3 | "contacts": [ 4 | "plehegar" 5 | ], 6 | "policy": "open", 7 | "repo-type": "rec-track" 8 | } --------------------------------------------------------------------------------