On Linking - Part 2
This is part 2 of my post on linking. See Part 1 for the previous post.
As demonstrated by AtomPub, linking can and does work. But, there are a couple of design hurdles to cross for a more widespread use of linking.
Descriptions
Let us say, I have an app that returns the representation of an address:
GET /address/home HTTP/1.1
Host: example.org
200 OK
Content-Length: xxx
Content-Type: application/xml
<address>
<link rel="edit self" type="application/xml"
href="http://example.org/address/home"/>
<street>1 Main Street</street>
<city>Some City</city>
</address>
(I could have used the Atom Syndication format for this representation, but that won't not change the point I am trying to make here).
Let me now write a client app that is capable of updating the address. Once I get the above representation, in my client app, I can start looking links with "edit" relations, and will find one. Then I will know that I can PUT to "http://example.org/address/home" to update the address. But how will I know what representation to submit? Can I include a zipcode in the representation? If so where? The point I am getting at is that, by looking at a link at run-time, I will not know how to create a representation. I need some extra information that tells me more about the PUT.
One option for me is to use a description language like WADL to describe the syntax of PUT. But here is a better way. I can specify a custom media type to describe an address, say, application/vnd.address+xml and use that in the representation:
GET /address/home HTTP/1.1
Host: example.org
200 OK
Content-Length: xxx
Content-Type: application/vnd.address+xml
<address>
<link rel="edit self" type="application/vnd.address+xml"
href="http://example.org/address/home"/>
<street>1 Main Street</street>
<city>Some City</city>
</address>
I can now use my a priori (i.e. development-time) understanding of the media type application/vnd.address+xml and link relation types to implement a client app to update the address through a URI found at runtime.
So, in order to use links, as a developer of server app, I need to specify the following:
- Link relations, i.e., the value of the "rel" attributes for various kinds of associations between resources.
- A repository of Application specific media types, with detailed descriptions for development-time reference.
Once I provide this information, do I still need description language like a WADL or WSDL to describe my interface? I don' think so. I can rely on media types and URIs (or URI templates) and the uniform interface for a description. Here is how.
| WADL | Linking and media types | |
|---|---|---|
| Discovery of starting point URIs | Discovered at development time | Discovered at development time |
| Discovery of other URIs | Same as above | Discovered at run-time by introspecting representations |
| Verbs to use on a given URI | Same as above | Discovered at run-time via HTTP OPTIONS |
| Media types available | Same as above | Content negotiation and links |
| Structures of representations | Schema associated with the description | Media type specifications |
For those that want to generate code from description languages, it is still possible to generate those from media type specifications. Each media type could refer to a schema. But I am not convinced that a description like WADL is needed.
URI Templates
The second hurdle is URI templates.
The user-facing web has been chugging along fine without URI templates. URI templates are nice to have, but the lack of templates in HTML has not stopped progress. The reason is that HTML has two powerful ways to deal with URIs, viz., links and forms. By way of links, servers can assign opaque URIs to resources, and clients are not required to decipher those URIs. HTML forms, on the other hand, provide a well-defined means to create URIs from user input and partial URIs. But, we have a problem when it comes to client apps that are not browsers, and servers that use non-HTML media types for representations. URI templates can give apps a way to design semi-opaque URIs (templates) so that clients can construct true URIs for making requests, but there is no formal way to communicate those templates to client apps.
To illustrate this point, let me extend the above example with a collection of addresses. The use case is for the client to be able to search the collection for addresses containing a search string. I can designate the following URI template for this purpose.
http://example.org/addreses?contains={search_string}
and provide some documentation about the "search_string" used in this template.
One option for me is to publish this URI for development use. But in the spirit of linking, what if I want to communicate this URI to the client at run-time? One compelling option is to overload the link element:
GET /addresses HTTP/1.1
Host: example.org
200 OK
Content-Type: application/vnd.addresses+xml
Content-Length: xxx
<addresses>
<link rel="self" href="http://example.org/addresses"/>
<link rel="next" href="http://example.org/addresses?start=10&count=10"/>
<link rel="search" href="http://example.org/addresses?contains={search_string}"/>
<address>
<link rel="edit self" type="application/vnd.address+xml"
href="http://example.org/address/home"/>
<street>1 Main Street</street>
<city>Some City</city>
</address>
<!-- more -->
</addresses>
As a client developer, I can now pick up the URI to search based on the link relationship "search", fill-in the token, and make a GET request to find addresses.
GET /addresses?contains=Seattle Host: example.org
But apparently, I am breaking a rule here. The link element defined in HTML and Atom require that the href attribute be a URI, but a URI template is not a valid URI. A URI parser would fail to parse the template used here. This means that I will need to extend the link element with, say, a template attribute and rewrite my representation as follows:
<addresses>
<link rel="self" href="http://example.org/addresses"/>
<link rel="next" href="http://example.org/addresses?start=10&count=10"/>
<link rel="search" template="http://example.org/addresses?contains={search_string}"/>
<address>
<link rel="edit self" type="application/vnd.address+xml"
href="http://example.org/address/home"/>
<street>1 Main Street</street>
<city>Some City</city>
</address>
<!-- more -->
</addresses>
This is still not valid, since Atom requires the href attribute. An alternative is to invent a new link element that allows URI templates, as suggested here and here, and rewrite the above as
<addresses>
<link rel="self" href="http://example.org/addresses"/>
<link rel="next" href="http://example.org/addresses?start=10&count=10"/>
<ns1:link xmlns:ns="org:example:some" rel="search"
template="http://example.org/addresses?contains={search_string}"/>
<address>
<link rel="edit self" type="application/vnd.address+xml"
href="http://example.org/address/home"/>
<street>1 Main Street</street>
<city>Some City</city>
</address>
<!-- more -->
</addresses>
That is the state of linking. Linking is as important as resources and uniform interface. It takes a bit more effort to evolve apps from POX to linked, but it can be done.
Oh, by the way, please stop calling URIs "end-points".
[Thanks to my colleague Korby Parnell for acting as a sounding board as I was writing these two posts.]


