Introduction
Hey all,
This page is dedicated to the development of standards/guidelines for RESTful WebHooks. This page should be used to throw around ideas about how it aught to be done. As these ideas become more structured and coalesce so may this page. I am no Wiki master so if you would like to define a more coherent structure please do.
Note: This is still a very rough concept as such you should expect that the recommendations on this page will change.
Why REST?
WebHooks naturally lends itself to a RESTful design pattern. WebHooks are simple HTTP messages that communicate a change in the state of a web resource. One of the goals of WebHooks is to create a truly programmable web; allowing regular users to connect the various web apps that they interact with in their daily lives. WebHooks is providing a means to publish events to the web and as such should speak the language of the web, RESTful HTTP. The primary weakness of double wrapped envelopes such as SOAP are that they require the consumer to understand both the payload as well as the syntax of the envelope. This creates unnecessary complexity; imagine having to parse a SOAP envelope just to find out that it doesn’t actually contain anything and is just a notification of a change. Does this mean that we must abandon all things complex? Must we avoid XML Schema and service description languages because they are too complex? No, RESTful web hooks should embrace existing tools such as WSDL, WADL, and XML Schema, however, these tools should only be used to enhance the development experience and not as a prerequisite to entry.
Discovery
RESTful WebHooks discovery is very simple. Add /web-hooks to the end of any URL path and issue a HEAD command. WebHooks returns the HTTP headers detailing the payload formats that the WebHook can communicate in as well as information about service description resources. This mechanism is so simple it can easily be performed by humans and bots alike. It also prevents us from having to define special URLs or repositories for WebHooks discovery; WebHooks are sewn directly into the fabric of the web and are placed relative to the resource whose events they publish. This has the added benefit of allowing scoped event subscription. For example I could add a WebHook that listens to CREATED events at www.blog.com/posts/web-hooks and get notified about any new blog posts, or I could listen only for the UPDATED event of a particular post: www.blog.com/posts/post/2009/10/6/web-hooks. Search engines could even provide notification of WebHooks support directly in search results. Below is an example of WebHooks discovery request (note that HEAD is used, this prevents us from downloading a 2 hour film named “web-hooks”):
HEAD http://www.webapp.com/resource/web-hooks
200 Ok
X-WebHooks-Allow : text/json, text/xml, rss/xml, atom/xml
X-WebHooks-Help : http://www.webapp.com/web-hooks/help
X-WebHooks-Events : CREATED, ACCESSED, UPDATED, DELETED
“X-WebHooks-Allow” notifies us of the formats the WebHook can be broadcasted in and X-WebHooks-Help is a URL to a help resource for this WebHook or all the WebHooks for the site. There could be additional URLs to WSDL/WADL description etc. I am not clear on the best policy for this yet. There could also be additional attributes such as subscription expiration date or other policy info.
Subscription
Subscribing to WebHooks is nearly as simple as discovery. We use the URL that was discovered for all subscription tasks. Because a WebHook is a RESTful resource we can use standard HTTP methods. To check the status of a subscription we issue a GET command, to subscribe POST, to update PUT and to unsubscribe DELETE.
Subscribe:
POST http://www.webapp.com/resource/web-hooks
X-WebHooks-Accept : text/json, text/xml
X-WebHooks-Events : CREATED, DELETED
http://www.myapp.com/mylistener
201 Created
Location : http://www.webapp.com/resource/web-hooks/web-hook/1423246
Subscription Status:
GET http://www.webapp.com/resource/web-hooks/web-hook/1423246
200 Ok
X-WebHooks-Allow : text/json, text/xml, rss/xml, atom/xml
X-WebHooks-Help : http://www.webapp.com/web-hooks/help
X-WebHooks-Events : CREATED, DELETED
Update Subscription:
PUT http://www.webapp.com/resource/web-hooks/web-hook/1423246
X-WebHooks-Accept : text/json, text/xml
X-WebHooks-Events : UPDATED
202 Accepted
X-WebHooks-Allow : text/json, text/xml, rss/xml, atom/xml
X-WebHooks-Help : http://www.webapp.com/web-hooks/help
X-WebHooks-Events : CREATED, UPDATED, DELETED
Unsubscribe:
DELETE http://www.webapp.com/resource/web-hooks/web-hook/1423246
X-WebHooks-Events : ALL
202 Accepted
X-WebHooks-Allow : text/json, text/xml, rss/xml, atom/xml
X-WebHooks-Help : http://www.webapp.com/web-hooks/help
WebHooks subscriptions are pretty straight forward. There are a couple important details to point out. First, subscription can support authentication through standard HTTP headers (WWW-Authenticate) and the OPTIONS command can be used to determine what subscription options are allowed for a particular user. In general any user that has permission to get a WebHooks message should have full subscription privileges, but I can imagine circumstances where a user is allowed to unsubscribe but not re-subscribe. Another important feature of RESTful WebHooks is that it returns the URL at which the subscription resource resides; this URL is used to modify the subscription. This is a double edged sword; on one hand it improves security on the other it may require that the user store this URL in order to modify the subscription (if they wish to modify a subscription between event publications as events contain the id). I would recommend this approach to publicly subscribable WebHooks that do not require credentials. If the site requires authentication to subscribe then the target URL could be used as the ID for subscription operations. I have seen additional security measures prescribed for the subscription process; in particular Daniel Parker suggests that target URLs be sent confirmation messages to make sure that Evil Doers are not subscribing random URLs to WebHooks. I think this decision should be left to the provider, but I think we should establish guidelines for this approval process.
Publication:
Once subscribed the target URL will start receiving WebHooks messages. These messages should contain standard WebHooks information. The payload of the event should be of the X-WebHooks-Accept type specified in the subscription (assuming it was an X-WebHooks-Allowed type).
POST http://www.myapp.com/mylistener
Content-Type : text/json
Content-Location : http://www.webapp.com/resource
X-WebHooks-Id : http://www.webapp.com/resource/web-hooks/web-hook/1423246
X-WebHooks-Url : http://www.webapp.com/resource/web-hooks
X-WebHooks-Event : CREATED
200 Ok
The published event should identify the type of the payload using the Content-Type and should identify the resource that published this event using the Content-Location (or Location) HTTP attribute. The URL of the subscription resource is included using the X-WebHooks-Url and the event is specified with X-WebHooks-Event. In addition RESTful WebHooks could support batched notifications using HTTPs multi-part messages.
What is left?
The are a number of details that have been left out of this initial definition:
- Support for canceling events, eg. returning 406 “Not Acceptable” or other codes to cancel events.
- Should redirects be followed when publishing an event.
- Should subscriptions be automatically dropped on certain response status-codes etc.
- There is as yet no definition for pre and post event types.
- What should the payload be? Should it be info about the event? Should it be the resource that raised the event?
Part of the reason these, and other features, have not been addressed is because for the most part they rely on the policies of the event publisher. For example, canceling an event requires that the publisher wait for a response before continuing execution preventing send-and-forget publication. While I do not think RESTful WebHooks should mandate standards for these behaviors we should identify common patterns and recommend best practices for these different approaches.
Comments (0)
You don't have permission to comment on this page.