The underlying premise of this investigation is that REST is less useful that it could be due to concerns about a) interoperability, and b) discoverability. To address this, we propose adopting microformat-style conventions to further constrain the ways REST already constrains web services.
In particular, we constrain REST to work with existing web browser clients -- yet also be machine-parseable. This means:
- All inputs must be url-encoded (or maybe mime/multipart)
- All output must be XHTML, either:
- All URI links must be encoded as either:
- Anchors (<a&rt;) (via 'href')
- Forms (<a&rt;) (via 'action')
- Only GET and POST actions are supported
This may seem very strict, but that's the point: by adding more constraints, we reduce gratuitous degrees of freedom and enable greater consistency.
This may not solve every conceivable problem, but it should handle the 50% case pretty well:
- REST: 80% of web services
- XHTML: 80% of XML expressiveness
- GET/POST + urlencoding: 80% of queries
or, put another way:
- 80% x 80% x 80% = 51.2% of the benefit for
- 20% x 20% x 20% = 0.8% of the effort
To make parsing and auto-discovery easier -- and also simplify the design process -- we propose the following additional conventions.
As usual in REST, every noun must be a URI. However, we explicitly define three types of URIs:
- base;The base URI for the web service, e.g.:
- records;URIs representing individual entities, e.g.:
- tables;The URIs used to create or search for those instances, e.g.:
Note that each record is defined by a set of key-value pairs living under that table.
There can also be 'singletons' - a class which only has a single instance.
Even though REST allows four possible HTTP actions (GET, POST, PUT, and DELETE) we only use two: GET & POST, for compatibility with existing web clients. While that may seem overly restrictive, as a practical matter those cover the "80%" of public web services we are trying to solve (after all, you are welcome to use your own private methods if you need to).
Even better, we can define very precise semantics for what GET & POST mean for each of the different nouns:
GET base GET base?view=api # Return hyperlinks and forms GET base?query # search for records across multiple table
GET table GET table?view=api GET table?query # search for records in that table POST table?create # create record
GET record # encode as xoxo GET record?view=edit # encode as hyperlinks/anchors GET record?view=api # encode as hyperlinks/anchors + descriptions POST record?update # update record
For simplicity, we assume:
- users can not delete anything
- users can not create tables (or singletons)
To be sure, there are natural ways to extend this protocol to provide that functionality. However, as that is primarly for admin usage, and thus a private API, we're glossing over it here. From a user's point of view, we provide analogous capabilities using POST:
- "DELETE" is replaced by "mark for deletion"
- "PUT" is replaced by "ask table to create record"
Results should be returned in a xoxo-compatible format. In particular, query results should leverage OpenSearch 1.1.
[Do HTML bindings for this already exist?]
Questions for further research
- How to specify whether a field is optional or required?
Anchor Design Pattern
<a class="deth" href="http//somesite.com/prog/adduser">label</a>