Buckybase microprotocol: closer to the REST-metal
Can your website be your API? -- Kevin Marks and Tantek Çelic
This is an access protocol and document microformat (based on XHTML 2.0 metadata attributes) for the data model introduced in Buckybase, a document database with bidirectional hyperlinks and reverse chronological access*:
- Every page has a unique name.
- A page has any number of user-defined fields.
- All fields are multi-valued and ordered (single-value fields are just multi-valued fields with one value).
- Field values can be XML snippets or links to other pages. (A field may contain a mixture of XML and links as values.)
- Inverse fields are automatically made available and contain backlinks. However, the order of inverse fields cannot be set manually.
A Buckybase server has many accounts. An account has many folders. A folder contains many pages. Folders serve as units of syndication and access control.
This protocol uses simple, tailored REST requests (GET, PUT, POST, and DELETE to hierarchical, guessable URLs with arguments) to access and manipulate the accounts, folders, and pages of a Buckybase server.
Any kind of XML (not only HTML, but also RSS or SVG) can be used for pages, as long as a small number of XHTML 2.0 attributes from the Metainformation module (about, rel, rev, href, property) are used to express fields with links and XML values.
Sample Page
A sample page that represents a bug report:
Software doesn't exist yet
<div about="http://buckybase/manuel/bugs/bug-1"
xmlns:buckybase="http://buckybase.googlecode.com/">
<h1 property="buckybase:title">Software doesn't exist yet</h1>
<div property="buckybase:notes">Would be nice to have it by the end of 2006.</div> <div property="buckybase:notes">2007 ain't bad either.</div> <div property="buckybase:notes">Is also more realistic.</div
Related:
<a rel="buckybase:related" href="http://buckybase/manuel/bugs/bug-2">bug-2</a>,
<a rel="buckybase:related" href="http://buckybase/manuel/bugs/bug-3">bug-3</a>.
</div>
Base
List accounts
GET http://buckybase/
<div xmlns:buckybase="http://buckybase.googlecode.com/">
Accounts:
<a rel="buckybase:account" href="http://buckybase/manuel">manuel</a>, <a rel="buckybase:account" href="http://buckybase/zini">zini</a>.</div>
If you get http://buckybase/, the returned representation is usually HTML, but any XML, for example RSS or Atom feeds, or a SVG file is possible.
The returned XML has hyperlinks to all registered accounts, expressed using <link> or <a> tags. <link> and <a> can appear anywhere in the page. The <link> and <a> elements need a rel attribute of "buckybase:account" and the "buckybase" namespace prefix must be defined.
Account
Create account
POST http://buckybase/?account=...&password=...
Creates a new account with the given account name and password, and redirects to its location. If the account already exists, an error is returned instead.
List account's folders
GET http://buckybase/account
<div xmlns:buckybase="http://buckybase.googlecode.com/">
Folders:
<a rel="buckybase:folder" href="http://buckybase/manuel/bugs">bugs</a>,
<a rel="buckybase:folder" href="http://buckybase/manuel/blog">blog</a>,
<a rel="buckybase:folder" href="http://buckybase/manuel/wiki">wiki</a>.
</div>
An account's representation contains hyperlinks to all folders of the account.
Delete account
DELETE http://buckybase/account
Folder
Create folder
POST http://buckybase/account?folder=...
Creates a new folder with the given folder name and redirects to its location. If the folder already exists, an error is returned instead.
Feed of folder's recently updated pages
GET http://buckybase/account/folder
A folder is represented either as a RSS or Atom feed, or as an arbitrary XML with a feed autodiscovery link. The feed should include an entry for each recently updated page.
Upload binary media to folder
POST http://buckybase/account/folder
Redirects to the created resource, or returns an error. The created resource can be updated with PUT and deleted with DELETE.
Delete folder
DELETE http://buckybase/account/folder
Page
Show page
GET http://buckybase/account/folder/page
If you would get bug-2, the page would look like this:
<div about="http://buckybase/manuel/bugs/bug-2"
xmlns:buckybase="http://buckybase.googlecode.com/">
<h1 property="buckybase:title">OutOfCoffeeException</h1>
<div property="buckybase:notes">Starbucks at People's Square is nice.</div>
Related of:
<a rev="buckybase:related" href="http://buckybase/manuel/bugs/bug-1">bug-1</a>
</div>
Update page
PUT http://buckybase/account/folder/page
Send XML with metainformation. Inverse fields (rev attribute) are ignored.
Delete page
DELETE http://buckybase/account/folder /page
HTTP API Summary
Base
List accounts
GET http://buckybase/
Account
Create account
POST http://buckybase/?account=...&password=...
List account's folders
GET http://buckybase/account
Delete account
DELETE http://buckybase/account
Folder
Create folder
POST http://buckybase/account?folder=...
Feed of folder's recently updated pages
GET http://buckybase/account/folder
Upload binary media to folder
POST http://buckybase/account/folder
Delete folder
DELETE http://buckybase/account/folder
Page
Show page
GET http://buckybase/account/folder/page
Update page
PUT http://buckybase/account/folder/page
Delete page
DELETE http://buckybase/account/folder /page
Details of metadata reconstruction from XML
The rule to (re)construct fields of a page from such a representation:
For every element that has a property, rel, or rev attribute:
Get the current page from the inherited about attribute.
If element has a property attribute then:
Add the content of element as XML at the end of the current page's property field.
Else if element has a href attribute (rel or rev attribute implied) then:
Add href as a hyperlink at the end of the current page's rel or rev field.
The values of the property, rel, and rev attributes must be prefixed with a namespace, e.g. buckybase:related, and this namespace must be defined as per XML.
The current page, to which these fields apply, must be defined as a URI with the about property, as per XHTML 2.0 at or above the current element in the XML tree.
The reasoning is that any adequate programming language has libraries for pragmatic XML parsing and various syndication feed flavors. The special attributes are taken from XHTML 2.0 under the assumption that clients that don't understand them will simply ignore them. They can easily be matched using XPath 1.0 which is widely supported.
This microprotocol requires only real-world XML and feeds as medium. This means that a system can design its output the way it wants, as long as minimal metainformation is embedded in the markup.
Remarks
HTTPS should be used, as account creation passes the account's password in the URL.
All operations are subject to HTTP authentication for access control, but it is up to the server to decide the details (Basic or Digest, realms, admin accounts, ...).
RDFa is very similar syntactically, but semantically different, because it is RDF-based, and not on the Buckybase data model. Also, RDFa's triple-extraction rule is much more complicated than Buckybase's metadata reconstruction.
* The only difference is that field values are generally hyperlinks or XML (instead of strings).
Tom asked 'why no "page create"'.
The reason is that all pages exist already all the time, if you don't mind us saying so.
Like in RDF, a page is only a name, to which you PUT metadata.
Posted by:Manuel Simoni | October 29, 2006 at 02:41
Need to incorporate the following changes:
- Require that feed is Atom.
- Create an Atom Media Link Entry for each uploaded file.
- Indicate location of created resources not through redirect, but a 201 Created response with a Location header.
Posted by:Manuel Simoni | October 31, 2006 at 01:43