For HTTP headers it's quite straightforward: draft-nottingham-http-link-header defines this.
Link: <http://example.com/>; rel="previous"; titile="Previous chapter"
Perl's LWP library automatically parses this headers, and in Ruby there's link_header gem.
Implemented in GitHub API v3.
There's a couple of ways to embed links inside a JSON data structure. Here's the list I can come up with:
{
"id": 1234,
"name": "Bob",
"links": {
"self": "/people/1234"
}
}
Pros:
- Simple. Easy to parse and access in client libraries
Cons:
- Can't include attributes other than
href
. What if I want to includetitle
andtype
for example? - Can't have multiple links with the same
rel
, although i think it is a bad practice to have multiple links with the same relationship anyway.
Facebook Graph API implements this format under connections
if you request the API with ?metadata=1
.
{
"id": 1234,
"name": "Bob",
"links": {
"self": { "href": "/people/1234" },
}
}
Pros:
- Easy to parse, yet extensible and can include other attributes
Cons:
- Can't have multiple links with the same rel. Same as above.
GitHub API v3 implementes this format in some of the data types.
{
"id": 1234,
"name": Bob,
"links": [
{ "rel": "self", "href": "/people/1234" }
]
}
Pros:
- Extensible and straightforward.
Cons:
- A little bit annoying to parse, although it could be still one-line
grep
orselect
in most languages, and you can write a wrapper anyway.
Ruby gem roar implements this format.
I mean that you, as the producer of your API should be.
Accept
headers are how clients request a specific type they have knowledge of.What you're doing here is defining a media type; extra semantics on top of something. application/json has no link semantics, so as soon as you say "We're serving application/json, but we're adding a 'links' element to each response", you've created a new media type, just given it no name for a client to
Accept
against!This is why Fielding says A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]
If you don't formalize and document the media type, the fact that you have a 'links' section is out-of-band knowledge, and breaks the 'self-descriptive messages' sub-constraint of the uniform interface constraint.