<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>brain.dump()</title>
 
 <link href="http://pvande.net/" />
 <updated>2013-03-11T14:40:24-07:00</updated>
 <id>http://pvande.net/</id>
 <author>
   <name>Pieter van de Bruggen</name>
   <email>pvande@gmail.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/pvande" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="pvande" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Open Questions About REST APIs, Part II</title>
   <link href="http://pvande.net/blog/Open-Questions-About-REST-APIs-Part-II" />
   <updated>2013-01-20T00:00:00-08:00</updated>
   <id>http://pvande.net/blog/Open-Questions-About-REST-APIs-Part-II</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;What follows is a fairly wandering article that covers two very important
topics: versioning and content types. Please do try to bear through.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another common discussion in the REST-over-HTTP world is that of long-term
maintainability: specifically, how can we introduce versioning so that our
existing clients rarely (if ever) break as we make changes. The question of
&lt;em&gt;what&lt;/em&gt; to version is much more rarely asked, and has led to a quite a bit of
conflicting advice and mis-applied best practices.&lt;/p&gt;

&lt;h2&gt;Versioning Interfaces&lt;/h2&gt;

&lt;p&gt;Represented simply, REST is describing a system where a &lt;strong&gt;client application&lt;/strong&gt;
asks a &lt;strong&gt;service&lt;/strong&gt; for a &lt;strong&gt;representation&lt;/strong&gt; of a &lt;strong&gt;named resource&lt;/strong&gt;. While this
is only a small subset of the number of systems involved in actually
implementing a RESTful service, these are the places where HTTP interface
designers most commonly discuss versioning. Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client versioning&lt;/li&gt;
&lt;li&gt;Server versioning&lt;/li&gt;
&lt;li&gt;URI versioning&lt;/li&gt;
&lt;li&gt;Schema versioning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A version is little more than a label we apply in order to give things context.
They serve as guideposts, giving us the ability to calculate distances, make
promises about compatibility, and to locate faults and shortcomings within our
codebase and within time.&lt;/p&gt;

&lt;h3&gt;Application Versioning&lt;/h3&gt;

&lt;p&gt;Given that context, we can easily derive value from the versions we give our
applications and libraries, especially as software is shipped to the real
world. By including that version information in requests and responses, we can
gauge adoption of new versions and discover compatibility-related faults. The
HTTP spec even encourages the inclusion of these kinds of information, in the
&lt;code&gt;User-Agent&lt;/code&gt;, &lt;code&gt;Server&lt;/code&gt;, and &lt;code&gt;Via&lt;/code&gt; headers.&lt;/p&gt;

&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; also use that version information to selectively serve (or request)
different (read: compatible) content. While this has been done for years (with
moderate success) as a workaround for poorly behaving web browsers, the
approach lacks most of the stability desired of a programatic API.&lt;/p&gt;

&lt;h3&gt;URI Versioning&lt;/h3&gt;

&lt;p&gt;Versioning a URI scheme is a tricky proposition. On the one hand, you can spend
weeks designing a perfect URI hierarchy for your application&amp;#39;s resources, and
really nail the execution so that your URIs never have to change again. On the
other hand, you&amp;#39;re not prescient. You&amp;#39;ll miss things. Your user&amp;#39;s needs will
change. Even in the best case, unless you&amp;#39;re developing and abandoning the
simplest of tools, ongoing development makes it highly likely that your data
model will eventually change, making your carefully crafted URI scheme obsolete.&lt;/p&gt;

&lt;p&gt;In the worst of all possible cases, you realize that you need to completely
rearchitect your API. Backwards incompatible, no hope for redemption. Oh,
you&amp;#39;ll still have to keep the old API around for legacy clients, but you need a
clean slate…&lt;/p&gt;

&lt;p&gt;Like a storybook hero, &lt;code&gt;/api/v2&lt;/code&gt; bursts through the door and proclaims its
heroism – and in some ways, it may be right. &lt;a href="http://www.w3.org/Provider/Style/URI"&gt;Cool URIs don&amp;#39;t change&lt;/a&gt;,
and making the version number a part of the URI makes it easy to guarantee that
no matter what changes, they&amp;#39;ll never have to. Perfectly future-proof.&lt;/p&gt;

&lt;p&gt;Except, the version number isn&amp;#39;t actually a part of the resource&amp;#39;s name, so now
you have multiple names (URIs) for the same resource. Not exactly a
deal-breaker, but more complex. Also, by embedding a version number in the URI,
you&amp;#39;ve created the place version numbers &lt;em&gt;live&lt;/em&gt; – and the temptation to
increment that version number for purposes other than URI scheme versioning is
fairly significant.&lt;/p&gt;

&lt;p&gt;What you actually want is a form of &lt;strong&gt;path namespacing&lt;/strong&gt;, in much the same way
you might namespace a class or a function. Putting the version information
mid-path is certainly a simple way to handle that, but putting it at the front
of the path (say, as a subdomain) has many of the same drawbacks. (As an aside,
Facebook did exactly this when it deprecated &lt;code&gt;api.facebook.com&lt;/code&gt; in favor of
&lt;code&gt;graph.facebook.com&lt;/code&gt;.) Thankfully, path namespacing – and URI versioning in
general – are largely unnecessary in a RESTful
&lt;a href="/blog/Open-Questions-About-REST-APIs-Part-I/#links"&gt;hyperlinked API&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;The Internet is REST&lt;/h4&gt;

&lt;p&gt;Memorizing page addresses or pathing schemes isn&amp;#39;t a requirement for using the
Internet, and the reason is actually fairly simple: sites have a &amp;quot;well-known&amp;quot;
address (e.g. http://wikipedia.com/), and provide access to their content
through a few standard mechanisms (contextual links, HTML forms, etc.). That&amp;#39;s
it. There&amp;#39;s no documentation telling you how to get to construct URIs to get
what you need, no &lt;a href="http://homestarrunner.com/404"&gt;secret pages&lt;/a&gt;, and no special
functionality that can&amp;#39;t be reached without editing your browser&amp;#39;s location bar
(with &lt;a href="https://speakerdeck.com/holman/git-and-github-secrets"&gt;few exceptions&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This works because people who know what they&amp;#39;re looking for can find it by
following descriptive links towards their content, and people who don&amp;#39;t know what
they&amp;#39;re looking for can discover things by following those same links. This is
&lt;em&gt;the&lt;/em&gt; reason why REST mandates hypermedia links – it decouples the concepts and
relationships in your data model from the URI scheme.&lt;/p&gt;

&lt;p&gt;As &lt;a href="http://37signals.com/svn/posts/3373-getting-hyper-about-hypermedia-apis"&gt;some&lt;/a&gt; have pointed out, REST clients still need to encode &lt;em&gt;something&lt;/em&gt;.
When you&amp;#39;re building a client for a RESTful (hypermedia) interface, however,
you aren&amp;#39;t required to hardcode URIs (an implementation detail), but the named
concepts and relationships (the domain model) into your application. Not only
is that simpler to reason about, but it serves to abstract away the underlying
service, making the URIs themselves much less important.&lt;/p&gt;

&lt;h3&gt;Schema Versioning&lt;/h3&gt;

&lt;p&gt;This leaves us with the most volatile part of the API: the schema. Fortunately,
as with hypermedia links, many proposed solutions exist. As a set of goals for
a suitable versioning mechanism, I would expect it to be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow clients to request specific versions.&lt;/li&gt;
&lt;li&gt;Allow clients to specify more than one supported version.&lt;/li&gt;
&lt;li&gt;Include version information in the response when appropriate.&lt;/li&gt;
&lt;li&gt;Support non-GET requests.&lt;/li&gt;
&lt;li&gt;Play nicely with caching.&lt;/li&gt;
&lt;li&gt;Play nicely with existing HTTP standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Versions in URIs&lt;/h4&gt;

&lt;p&gt;While we&amp;#39;ve already dissected the use of versions as URI namespacing
mechanisms, some have argued that they may be an appropriate way to version the
schema as well.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/api/v3/user/joe&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple, convenient, and direct.&lt;/li&gt;
&lt;li&gt;Totally cacheable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conflates the resource name and the version string.&lt;/li&gt;
&lt;li&gt;Single version only.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;p&gt;Query strings are another in-URI way of communicating a request for a
particular schema version. This avoids the problem of embedding the
representation version in the resource name, but unfortunately ties it to the
request instead - not to the desired representation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/user/joe?version=3&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/user/joe?version=3.x&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/user/joe?version=3&amp;amp;version=4&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple, convenient, and direct.&lt;/li&gt;
&lt;li&gt;Totally cacheable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version is not, strictly speaking, a parameter of the request.&lt;/li&gt;
&lt;li&gt;Behaves poorly with non-GET requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These aren&amp;#39;t actually awful solutions – not really – but they do quickly create
problems for more complex APIs. Imagine asking yourself, &amp;quot;Does the v2
representation of a user support comments? Which representation versions are
supported?&amp;quot;&lt;/p&gt;

&lt;p&gt;To look at it from a different perspective, embedding versions in the path is
akin to calling &amp;quot;5-year-old Jimmy&amp;quot; a completely different entity from
&amp;quot;50-year-old Jimmy&amp;quot;. While Jimmy is certainly more mature at age 50, the hope
is that he would (at some level) be identifiable as the same individual.
Versions in the query string are somewhat like asking to see Jimmy (at 50) is
his 5-year-old clothing.&lt;/p&gt;

&lt;p&gt;What we really want to see is a &lt;em&gt;photograph&lt;/em&gt; of Jimmy at age 5. If that
information can&amp;#39;t be modeled well in the URI, maybe we can fit it in the
headers…&lt;/p&gt;

&lt;h4&gt;Custom Version Headers&lt;/h4&gt;

&lt;p&gt;The simplest way to push this kind of information into the headers is simply to
do it ad-hoc. If that notion doesn&amp;#39;t appeal to you, you could probably also
find a proposed standard to latch onto.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/users/1&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;span class="na"&gt;X-API-Version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;3.x || 4.2.0 - 4.5.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;X-API-Version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;3.2.4&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Vary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;X-API-Version&lt;/span&gt;

&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows a variety of version range syntaxes.&lt;/li&gt;
&lt;li&gt;Supports non-GET requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-standard (but permitted).&lt;/li&gt;
&lt;li&gt;A header like this is still a parameter of the request itself, not of the
representation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is more or less equivalent to the query string example offered earlier,
with a couple of drawbacks. It&amp;#39;s regrettably difficult to link directly to a
specific representation version with headers. As a further complication,
caching is easily broken if you omit the appropriate &lt;code&gt;Vary&lt;/code&gt; header (which is
used to specify on which request headers the current response is based).&lt;/p&gt;

&lt;p&gt;Perhaps most frustratingly, while all of the discussed options are functional,
none of them actually addresses the core issue: specifying a representation
version. There is, however, something built into the HTTP spec for that very
purpose.&lt;/p&gt;

&lt;h4&gt;Content Type Headers&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Accept&lt;/code&gt; and &lt;code&gt;Content-Type&lt;/code&gt; headers are used by HTTP agents to communicate
about the type of data being transferred. Before we dig too deeply into how
they might apply to versioning, we should first examine how they&amp;#39;re intended to
be used in general.&lt;/p&gt;

&lt;p&gt;These headers both use standard &lt;a href="http://tools.ietf.org/html/rfc1341"&gt;MIME types&lt;/a&gt; to describe the format of
the contained content. Other content attributes such as encoding, (spoken)
language, and character set are notably &lt;em&gt;not&lt;/em&gt; a part of this particular
conversation – other headers handle those attributes. As a refresher, the
general format of a MIME type is this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="text"&gt;{type}/{subtype} (; {parameter.name}={parameter.value})*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;type&lt;/code&gt; is defined to be one of eight primary groups, &lt;code&gt;text&lt;/code&gt;, &lt;code&gt;image&lt;/code&gt;, &lt;code&gt;audio&lt;/code&gt;,
&lt;code&gt;video&lt;/code&gt;, &lt;code&gt;application&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;message&lt;/code&gt;, or &lt;code&gt;multipart&lt;/code&gt;. The first four are
exactly what they sound like, with &lt;code&gt;application&lt;/code&gt; serving as both executable
code and as a kind of binary &amp;quot;catch-all&amp;quot;, &lt;code&gt;model&lt;/code&gt; providing a way to describe a
3D mesh, &lt;code&gt;message&lt;/code&gt; representing a mail message, and &lt;code&gt;multipart&lt;/code&gt; being a way to
include multiple pieces of data in the same communication.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;subtype&lt;/code&gt; is a &lt;a href="http://www.iana.org/assignments/media-types"&gt;registered&lt;/a&gt; data format name, usually corresponding to
the well-known name of the format. &lt;code&gt;image/png&lt;/code&gt;, &lt;code&gt;text/plain&lt;/code&gt;, and
&lt;code&gt;application/javascript&lt;/code&gt; should all feel pretty familiar. There also exist
provisions in the RFCs for &lt;a href="http://tools.ietf.org/html/rfc4288#section-3.2"&gt;proprietary, personal, and experimental&lt;/a&gt;
subtypes, though these are likely &amp;quot;policed&amp;quot; somewhat less rigorously.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;parameter&lt;/code&gt;s are, unsurprisingly, key-value pairs that provide additional
context for the format. As an example, some &lt;code&gt;audio&lt;/code&gt; subtypes may define a
&amp;#39;bitrate&amp;#39; parameter, denoting the audio quality. These parameters are a part of
the subtype&amp;#39;s (or occasionally the type&amp;#39;s) registered description, have very
specific meanings, and may be declared as either required or optional. To quote
from &lt;a href="http://tools.ietf.org/html/rfc4288#section-4.3"&gt;the RFC&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;New parameters SHOULD NOT be defined as a way to introduce new functionality in
types registered in the standards tree, although new parameters MAY be added to
convey additional information that does not otherwise change existing
functionality. An example of this would be a &amp;quot;revision&amp;quot; parameter to indicate a
revision level of an external specification such as JPEG. Similar behavior is
encouraged for media types registered in the vendor or personal trees but is
not required.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5&gt;Content Type Negotiation&lt;/h5&gt;

&lt;p&gt;One of the goals behind HTTP was to reduce the amount of round-trip
communication required to fetch a resource. To that end, a negotiation protocol
was built-in. The rules break down thusly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Accept&lt;/code&gt; header of the request should contain an unordered, non-empty set
of comma-separated MIME media types, including parameters.&lt;/li&gt;
&lt;li&gt;Each MIME media type in the &lt;code&gt;Accept&lt;/code&gt; header may have a special parameter &lt;code&gt;q&lt;/code&gt;,
with a value between 0 and 1 indicating the agent&amp;#39;s relative preference for
that media type. In the absence of the parameter, a value of 1.0 is assumed.&lt;/li&gt;
&lt;li&gt;Both the MIME type&amp;#39;s &lt;code&gt;type&lt;/code&gt; and &lt;code&gt;subtype&lt;/code&gt; subtype fields may (independently)
have a special value of &amp;#39;*&amp;#39;, which acts as a wildcard.&lt;/li&gt;
&lt;li&gt;Precedence of types with identical &lt;code&gt;q&lt;/code&gt; values should be ordered by
specificity. The term itself seems loosely specified, but a general algorithm
might be:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="text"&gt;  (non-wildcard type) + (2 * (non-wildcard subtype)) + (3 * parameter count)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;In the absence of clear precedence, the server is free to choose based on its
own preferences.&lt;/li&gt;
&lt;li&gt;In the absence of an &lt;code&gt;Accept&lt;/code&gt; header, the server should assume a type of
&lt;code&gt;*/*&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Similar rules apply to all the &lt;code&gt;Accept-*&lt;/code&gt; and &lt;code&gt;Content-*&lt;/code&gt; headers.)&lt;/p&gt;

&lt;p&gt;With this setup, an agent can make a single request of the server for any data
format it can handle, specify its own &lt;em&gt;preferences&lt;/em&gt;, and (usually) expect to
get back meaningful data. Applying these principles to a REST-over-HTTP
interface seems valuable, but finding an appropriate granularity may be
difficult.&lt;/p&gt;

&lt;h5&gt;Meaningful Content Types&lt;/h5&gt;

&lt;p&gt;As an example, let&amp;#39;s pick on &lt;code&gt;application/json&lt;/code&gt; for a minute. JSON is a great
transport format, balancing simplicity of parsing with human readability. But,
if our application is &lt;em&gt;generating&lt;/em&gt; JSON (as opposed to simply serving JSON
files from an unknown source or sources), is the general type
&lt;code&gt;application/json&lt;/code&gt; really the most appropriate descriptor? Well … maybe not.&lt;/p&gt;

&lt;p&gt;Atom and RSS are just particular XML schemata, but a feed reader wouldn&amp;#39;t want
to accept arbitrary XML. Instead, it &lt;code&gt;Accept&lt;/code&gt;s the more specific
&lt;code&gt;application/atom+xml&lt;/code&gt; and knows not only how to parse the data, but what the
data means. Great plan.&lt;/p&gt;

&lt;p&gt;Off you run to mint your own MIME type, say &lt;code&gt;application/x.myapp+json&lt;/code&gt;, but
something doesn&amp;#39;t quite feel right. Your content is in many ways just a
subclass of JSON, but naïve JSON parsers won&amp;#39;t recognize that. There&amp;#39;s a long
discussion of why the &lt;code&gt;+basetype&lt;/code&gt; syntax is &amp;quot;good enough&amp;quot; available in
&lt;a href="https://tools.ietf.org/html/rfc3023#appendix-A"&gt;the RFC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Is your MIME type granular &lt;em&gt;enough&lt;/em&gt;, though? You&amp;#39;ve got a type for your
application now, but you presumably return several distinct resource types from
your API, each with a different schema. Now you have an inheritance problem
again. &lt;code&gt;application/x.myapp.user+json&lt;/code&gt; isn&amp;#39;t bad, but you&amp;#39;ll need a separate
MIME type for each resource schema you expose, and there&amp;#39;s no programatic
relationship between those types and any internal conventions or external
standards they conform to.&lt;/p&gt;

&lt;p&gt;I would be uncomfortable if the content negotiation process implicitly &amp;quot;upcast&amp;quot;
the results of a request (e.g. &lt;code&gt;Accept: application/json&lt;/code&gt; -&amp;gt; &lt;code&gt;Content-Type:
application/x.myapp.user+json&lt;/code&gt;). On the one hand, it&amp;#39;s not the kind of response
I asked for (&amp;quot;do you support content negotiation properly?&amp;quot;), and on the other,
while it &lt;em&gt;is&lt;/em&gt; valid JSON, I can&amp;#39;t easily verify that by looking at the
Content-Type. &amp;quot;Downcasts&amp;quot; cause many of the same problems.&lt;/p&gt;

&lt;p&gt;If you want &lt;strong&gt;real&lt;/strong&gt; inheritance-like behavior for your application, you&amp;#39;re
usually stuck implementing it by hand. Your resource&amp;#39;s &lt;em&gt;proper&lt;/em&gt; MIME type is
&lt;code&gt;application/x.myapp.user+json&lt;/code&gt;, but you can write a server that will
automatically cast the result to any number of other implemented interfaces:
&lt;code&gt;application/x.myapp+json&lt;/code&gt;, &lt;code&gt;application/json&lt;/code&gt;, &lt;code&gt;application/hal+json&lt;/code&gt; (if
supported)… It&amp;#39;s far from ideal, but this is the only practical option I&amp;#39;m
aware of today.&lt;/p&gt;

&lt;h5&gt;Versions and Content Types&lt;/h5&gt;

&lt;p&gt;Now we actually have to answer the question of how that custom MIME type gets
versioned, and we &lt;em&gt;should&lt;/em&gt; also consider how that version plays with content
negotiation.&lt;/p&gt;

&lt;p&gt;At a glance, there are a few distinct ways to include the version:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;application/x.myapp.resource.v2+json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;application/x.myapp.resource-v2+json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;application/x.myapp.resource+json; version=2&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first option available feels strongly as if the version is an integral
component of the representation; neither a good nor a bad thing, but it doesn&amp;#39;t
ring true with how I tend to conceive of versioning. The first version of &lt;em&gt;X&lt;/em&gt;
is fundamentally related to the second version of &lt;em&gt;X&lt;/em&gt;, by more than just a
lexicographically similar name.&lt;/p&gt;

&lt;p&gt;The second option tries to make a distinction between the type name and the
version component by introducing another sub-name component. Whether the
concept of a &amp;quot;version&amp;quot; should be a parameter of a type seems to be the primary
division between options #2 and #3, so let&amp;#39;s dig into &lt;a href="http://tools.ietf.org/html/rfc1341"&gt;the RFC&lt;/a&gt; again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Parameters are modifiers of the content-subtype, and do not fundamentally
affect the requirements of the host system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Frankly … I don&amp;#39;t know what the &amp;quot;host system&amp;quot; is. Actually, I&amp;#39;m fully at a
loss. My sense of aesthetics prefers the separation offered by option #3, but I
can&amp;#39;t justify it well, and I won&amp;#39;t begin to claim to know the ideological
fallacies (or the real-world risks) I&amp;#39;d be committing to by using it for those
purposes. Then again, I&amp;#39;m finding it difficult to find heavily parameterized
media types.&lt;/p&gt;

&lt;p&gt;As much as I&amp;#39;d like to say, &amp;quot;just look at &lt;a href="http://developer.github.com/v3/media/#comment-body-properties"&gt;what GitHub does&lt;/a&gt;&amp;quot;, I&amp;#39;m
not particularly convinced by their approach either – most specifically, they
use a single vendor subtype (&lt;code&gt;vnd.github&lt;/code&gt;) and specify version and &amp;quot;param&amp;quot; as
dot-separated components of the subtype (&lt;code&gt;vnd.github.v3.raw+json&lt;/code&gt;). Notably
absent is any recognition of the represented resource schema: the &amp;quot;param&amp;quot; value
is only advice to the underlying responder e.g. about how to process Markdown
content. The responses they send actively &amp;quot;downcast&amp;quot; the content type to the
underlying format (e.g. &lt;code&gt;application/json&lt;/code&gt;), and the &amp;quot;actual&amp;quot; media type is
returned in a custom header.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;X-GitHub-Media-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;github.v3; param=full; format=json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;

&lt;p&gt;Content-Type versioning as a construct, however, seems useful, and in line with
the concerns of schema versioning.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/users/1&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/x.myapp.user+json; version=2; markdown=raw; compact=yes,&lt;/span&gt;
        &lt;span class="l"&gt;application/x.myapp+json; version=2; markdown=raw; q=0.8,&lt;/span&gt;
        &lt;span class="l"&gt;application/json; q=0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/x.myapp.user+json; version=2; markdown=raw; compact=yes&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1&amp;gt;; rel=&amp;quot;self&amp;quot;; type=&amp;quot;application/x.myapp.user+json; version=2; markdown=raw&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1/profile&amp;gt;; rel=&amp;quot;related&amp;quot;; type=&amp;quot;application/x.myapp.profile+json&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Vary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;Accept&lt;/span&gt;

{}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content-Type negotiation is a well-established standard for handling data
type resolution.&lt;/li&gt;
&lt;li&gt;Supports non-GET requests.&lt;/li&gt;
&lt;li&gt;Can be cached.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version information lives in the content type, so additional data is required
for Links.&lt;/li&gt;
&lt;li&gt;Finding the proper abstraction level in your MIME types can be difficult.&lt;/li&gt;
&lt;li&gt;MIME type inheritance is effectively non-existent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This feels like less of a &amp;quot;home run&amp;quot; than it should. I appreciate the clear
conceptual separation of the type parameters, but I&amp;#39;m not feeling great about
the custom MIME subtypes. Doing content negotiation for well-known formats is
awesome; doing content negotiation for unknown (or poorly known) formats is
distinctly less so. Communicating type information with each link is
particularly uncool – though that&amp;#39;s less an artifact of the versioning scheme,
and more about having so many distinct schemas throughout the application.&lt;/p&gt;

&lt;h4&gt;Versioning Well-Known Media Types&lt;/h4&gt;

&lt;p&gt;Let&amp;#39;s try a little mental exercise, and work backwards from our last
conclusion.&lt;/p&gt;

&lt;p&gt;Why did we end up with a content type of &lt;code&gt;application/x.myapp.user+json;
version=2&lt;/code&gt;? We got there by adding the version to the content type, as a
parameter. This gave us the ability to negotiate versions using the standard
content type negotiation, and fell neatly into a pattern whereby we could make
other &amp;quot;sub-schema&amp;quot; level alterations to our type.&lt;/p&gt;

&lt;p&gt;Before that, we had a content type of &lt;code&gt;application/x.myapp.user+json&lt;/code&gt;. We used
that content type to represent the schema of the returned data. Our subtype
name was built up from our namespace (&lt;code&gt;x.myapp&lt;/code&gt;), the schema name (&lt;code&gt;user&lt;/code&gt;), and
the general format of the data (&lt;code&gt;json&lt;/code&gt;). We would expect the schema to change
between almost every endpoint, but the format would likely remain constant for
a given client.&lt;/p&gt;

&lt;p&gt;Before that, we had a content type of &lt;code&gt;application/x.myapp+json&lt;/code&gt;. This was to
&amp;quot;strongly type&amp;quot; the data as belonging to our application (as opposed to being
generic content). This also gave us permission to freely declare and use type
parameters, as we were the owners of the type description.&lt;/p&gt;

&lt;p&gt;Before that, we were using &lt;code&gt;application/json&lt;/code&gt;, because that&amp;#39;s the well-known
MIME type for JSON content.&lt;/p&gt;

&lt;p&gt;We&amp;#39;ve already explored the possibilities around where else the version number
might live, and I still believe that the content type seems an appropriate
place for it. Let&amp;#39;s accept that as given for the moment, and see if there are
other assumptions we can challenge.&lt;/p&gt;

&lt;p&gt;Communicating about the schema itself seems important, but what if that
information didn&amp;#39;t live in the Content Type header?&lt;/p&gt;

&lt;p&gt;The first question I&amp;#39;d want to ask is, &amp;quot;how does that affect type negotiations?&amp;quot;
– and it seems to me that we would stop using different types for each
endpoint, which would promote the development of an abstract REST agent, in
addition to making clients easier to write as they have one fewer dimensions in
type names.&lt;/p&gt;

&lt;p&gt;The second question is, &amp;quot;where does the schema information live?&amp;quot; That may be a
trickier question, but there is a &lt;a href="http://tools.ietf.org/html/draft-wilde-profile-link-04"&gt;draft proposal&lt;/a&gt; for a &amp;quot;profile&amp;quot;
link relation intended for this very purpose. In fact, one of the targets of
that proposal is to be able to describe multiple profiles the content
deliberately adheres to. Let&amp;#39;s accept with the &amp;quot;profile&amp;quot; relation for now.&lt;/p&gt;

&lt;p&gt;The schema concerns addressed, let&amp;#39;s look back at our media type
(&lt;code&gt;application/x.myapp+json&lt;/code&gt;). The benefit this type gives us is twofold: it
communicates about the content producer, and it gives us a place to use type
parameters. As discussed earlier however, we&amp;#39;ve already got a much clearer
place to list the content&amp;#39;s producer in the Server header. We do (officially)
lose a place to attach type parameters; we&amp;#39;ll ignore that for the moment.&lt;/p&gt;

&lt;p&gt;When finally assembled, the solution we have looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/users/1&lt;/span&gt; &lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json; version=2; markdown=raw; compact=yes,&lt;/span&gt;
        &lt;span class="l"&gt;application/json; version=1; markdown=raw; compact=yes,&lt;/span&gt;
        &lt;span class="l"&gt;application/xml; version=2; markdown=raw; q=0.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.0&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json; version=2; markdown=raw; compact=yes&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/schema/user&amp;gt;; rel=&amp;quot;profile&amp;quot;; name=&amp;quot;user&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;http://stateless.co/hal_specification.html&amp;gt;; rel=&amp;quot;profile&amp;quot;; name=&amp;quot;HAL&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1&amp;gt;; rel=&amp;quot;self&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Vary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;Accept&lt;/span&gt;

&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content-Type negotiation is a well-established standard for handling data
type resolution.&lt;/li&gt;
&lt;li&gt;Content-Type negotiation is done around well-known types.&lt;/li&gt;
&lt;li&gt;Profile links allow something akin to inheritance.&lt;/li&gt;
&lt;li&gt;Supports non-GET requests.&lt;/li&gt;
&lt;li&gt;Can be cached.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version information doesn&amp;#39;t live in the URL, so additional effort is
required.&lt;/li&gt;
&lt;li&gt;Violates the specifications of well-known media types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From the perspective of the HTTP clients I&amp;#39;ve written, this seems fairly sane.
The content type is very likely to remain stable for the entirety of my
client&amp;#39;s life, and what changes &lt;em&gt;are&lt;/em&gt; made are flags that can be independently
tuned. Violating specs seems to be a growing theme here, but I&amp;#39;m not overly
concerned about it at the moment.&lt;/p&gt;

&lt;p&gt;All told, I feel reasonably comfortable with this solution (despite its
drawbacks). I may &lt;em&gt;also&lt;/em&gt; simply be unable to see the forest for the trees at
this point – please leave your thoughts and preferences in the comments.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Open Questions About REST APIs, Part I</title>
   <link href="http://pvande.net/blog/Open-Questions-About-REST-APIs-Part-I" />
   <updated>2013-01-01T00:00:00-08:00</updated>
   <id>http://pvande.net/blog/Open-Questions-About-REST-APIs-Part-I</id>
   <content type="html">&lt;p&gt;Designing an HTTP-based API is a fairly straightforward task, all things told.
A proper &lt;a href="http://en.wikipedia.org/wiki/Representational_state_transfer" title="Wikipedia: REST"&gt;REST&lt;/a&gt; API is a much smaller target, and while some of that
comes down to the constraints REST advocates for, a larger portion deals with
the long-term maintenance and evolution of that API.&lt;/p&gt;

&lt;h2&gt;The REST Constraints&lt;/h2&gt;

&lt;p&gt;REST is less about a protocol than it is about interface design, and the design
is constrained by a few principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clients and Servers communicate about identifiable resources.&lt;/strong&gt; These
communications take place using &lt;em&gt;representations&lt;/em&gt; of resources (XML, JSON,
PNG, etc.), and each resource has a globally unique identifier.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Each message is self-descriptive.&lt;/strong&gt; Content-Type is an oft used example
here; each message must clearly denote what types of content it contains, so
the recipient may handle it appropriately.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Each Client response contains enough information to manipulate the
resource.&lt;/strong&gt; If permitted to do so, the Client should have enough information
to delete or update a resource on the Server. That information may be in the
resource representation itself (e.g. the resource ID, a version identifier),
or elsewhere in the message.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client interactions are driven by hypermedia.&lt;/strong&gt; With few exceptions,
Clients are expected to &amp;quot;navigate&amp;quot; the API dynamically, rather than hard-code
service URL patterns. The most common example for this is the web as it
exists today: you tend to follow links rather than guess at URLs, and your
browser provides a handy mechanism for that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;REST-over-HTTP gives us a nice common ground for discussion. The model is
Client/Server, we&amp;#39;re not &lt;em&gt;actually&lt;/em&gt; passing the only copy of resources around,
messages are reasonably self-descriptive (thanks in part to HTTP headers), and
&amp;hellip; wait, &lt;a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven" title="REST APIs must be hypertext-driven"&gt;where are the links&lt;/a&gt;?&lt;/p&gt;

&lt;h3&gt;Links&lt;/h3&gt;

&lt;p&gt;This is the biggest difference between most &amp;quot;RESTful&amp;quot; APIs today and the core
definition of REST. In the absence of hypermedia links, you are left with a
resource-oriented Client/Server API with a limited set of available actions
(the HTTP verbs). While that&amp;#39;s certainly a valid API design, it requires
Clients to hardcode an understanding of the Server&amp;#39;s URI patterns and data
model, which ultimately leads to the brittleness and change-resistance that
REST seems best suited to avoid.&lt;/p&gt;

&lt;p&gt;This isn&amp;#39;t terribly surprising, either. Many of us learned what &amp;quot;REST&amp;quot; is by
restructuring our URIs into a resource hierarchy &amp;ndash; and for some of us,
that was itself a significant cognitive challenge. Even today, the Rails
documentation sometimes conflates resource-oriented with REST, and many books
&lt;a href="http://www.informit.com/articles/article.aspx?p=1671632"&gt;still omit hypermedia links&lt;/a&gt; from their definition of REST.&lt;/p&gt;

&lt;p&gt;Part of the reason for this is a lack of best practices. HTML has long used the
anchor tag (&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;) as a way of navigating collections of documents, and has
expressed other relationships in other ways (e.g. &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;,
&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;) &amp;ndash; you would be hard pressed to find an HTML document that
didn&amp;#39;t leverage links. XML can easily adopt some of these conventions, but JSON
(and many other representation formats) have a harder time of it.&lt;/p&gt;

&lt;p&gt;In an effort to derive a general solution, it may be useful to start with some
guiding parameters. A desirable solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows Clients to &amp;quot;follow their nose&amp;quot; through your application, starting from
a small number of known entry points.&lt;/li&gt;
&lt;li&gt;Permit Clients to avoid having to &amp;quot;guess&amp;quot; at URIs.&lt;/li&gt;
&lt;li&gt;Should be lightweight (in terms of both network and cognitive overhead).&lt;/li&gt;
&lt;li&gt;Can express links to alternate representations of the same resource, related
single resources, and members of a collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, a desirable solution need not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specify which actions are permitted for a link.&lt;/li&gt;
&lt;li&gt;Encode the links as a part of the resource representation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;JSON-LD&lt;/h4&gt;

&lt;p&gt;A JSON convention, &lt;a href="http://www.slideshare.net/gkellogg1/json-for-linked-data"&gt;JSON-LD&lt;/a&gt; has been described as a direct port of
RDF to JSON. In its simplest forms, you end up creating two parallel object
graphs &amp;ndash; one of your data, the other of links to other data. Tooling
exists to transform these disjoint graphs into a single, unified graph, in
addition to many other graph transformations.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="json"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;@context&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://xmlns.com/foaf/0.1/name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;homepage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;quot;@id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://xmlns.com/foaf/0.1/homepage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;quot;@type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;@id&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Manu Sporny&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;homepage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;http://manu.sporny.org/&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reasonably small footprint (few reserved property names).&lt;/li&gt;
&lt;li&gt;Links are provided in the data.&lt;/li&gt;
&lt;li&gt;Enables metadata for every field without altering data model.&lt;/li&gt;
&lt;li&gt;Allows external linkage to metadata descriptions, for readability.&lt;/li&gt;
&lt;li&gt;Easily extended beyond relationship metadata.&lt;/li&gt;
&lt;li&gt;Fairly well supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is only a solution for JSON.&lt;/li&gt;
&lt;li&gt;Complex metadata quickly overwhelms the original data.&lt;/li&gt;
&lt;li&gt;Seems primarily focused on describing types, not relationships.&lt;/li&gt;
&lt;li&gt;No fields can be assumed to be links.&lt;/li&gt;
&lt;li&gt;Semantics are not immediately clear.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A remarkably complete standard, but it feels distinctly cumbersome to achieve
the basic goals of hypermedia links. This is probably a good candidate for
something &amp;ndash; just not this.&lt;/p&gt;

&lt;h4&gt;HAL&lt;/h4&gt;

&lt;p&gt;Targeted squarely at JSON and XML, &lt;a href="http://stateless.co/hal_specification.html"&gt;HAL&lt;/a&gt; aims to standardize the discovery
of resource links, by storing them all in reserved properties.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="json"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;_links&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;self&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/orders&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;next&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/orders?page=2&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;find&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/orders{/id}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;templated&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;search&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/orders{?keyword}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;templated&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;_embedded&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;orders&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;_links&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;quot;self&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;href&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/orders/123&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;currency&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;USD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;status&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;shipped&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;total&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;30.1&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;currentlyProcessing&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;shippedToday&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reasonably small footprint (only two reserved property names).&lt;/li&gt;
&lt;li&gt;Links are provided in the data.&lt;/li&gt;
&lt;li&gt;Open set of link relationships.&lt;/li&gt;
&lt;li&gt;Fairly well supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is only a solution for XML and JSON.&lt;/li&gt;
&lt;li&gt;Obscures the interesting data somewhat.&lt;/li&gt;
&lt;li&gt;Forces nested JSON resources into the &lt;code&gt;_embedded&lt;/code&gt; key (somewhat unnatural).&lt;/li&gt;
&lt;li&gt;Requires a custom MIME type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;_links&lt;/code&gt; key does a nice job of providing an accessible table of contents
for links pertaining to the requested resource. The &lt;code&gt;_embedded&lt;/code&gt; key however,
which aims to aid discovery of nested resources, breaks common conventional
uses of JSON. This might be a viable solution, though it doesn&amp;#39;t generalize
beyond JSON.&lt;/p&gt;

&lt;h4&gt;Link Headers&lt;/h4&gt;

&lt;p&gt;The other main solution on the table leverages that big blob of metadata we
already send with every message: HTTP Headers. In fact, there&amp;#39;s already
&lt;a href="http://tools.ietf.org/html/rfc5988"&gt;an accepted standard&lt;/a&gt; for including linking information in
response headers.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;close&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/orders&amp;gt;; rel=&amp;quot;self&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/orders?page=2&amp;gt;; rel=&amp;quot;next&amp;quot;&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;stuff&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;moar-stuff&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero data changes.&lt;/li&gt;
&lt;li&gt;Works for all content types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Links are not provided in the data.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.iana.org/assignments/link-relations/link-relations.xml"&gt;Restricted set&lt;/a&gt; of link relationships &amp;ndash;
&lt;a href="http://tools.ietf.org/html/rfc5988#section-4.2"&gt;extensions&lt;/a&gt; are possible, but a bit kludgy.&lt;/li&gt;
&lt;li&gt;Doesn&amp;#39;t naturally describe links for nested resources.&lt;/li&gt;
&lt;li&gt;Less easily &amp;quot;discovered&amp;quot; by casual API consumers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This actually proves to be a fairly neat solution for REST-over-HTTP,
regardless of the representation. Where in an HTML document many of the links
are contextual, they are typically less contextual in API data &amp;ndash; given
that, keeping them in the message&amp;#39;s metadata may make a lot of sense.&lt;/p&gt;

&lt;p&gt;Not including the links in the representation data itself is a problem in a few
distinct circumstances, notably when the response headers aren&amp;#39;t available to
consumers (e.g. JSON-P requests). This problem is further exacerbated by the
fact that other important metadata may also be included in those headers, such
as status codes and API request limits.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://developer.github.com/v3/#json-p-callbacks"&gt;GitHub&lt;/a&gt; has implemented a solution for their own
API, where JSON requests containing a &lt;code&gt;callback&lt;/code&gt; parameter are served a
response (with a different MIME type) that invokes the named &lt;code&gt;callback&lt;/code&gt;
function, passing it a hash with two keys, &lt;code&gt;meta&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt;. The &lt;code&gt;data&lt;/code&gt; key is
identical to the standard JSON response, and the &lt;code&gt;meta&lt;/code&gt; key is a JSON
serialization of the relevant header information.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;callbackFunction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;meta&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* HEADERS */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* JSON */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the case of JSON-P, the header metadata could probably be passed as a second
parameter to the callback &amp;ndash; that would allow the received data to be
identical to the &amp;quot;standard&amp;quot; (i.e. JSON, no callback) response, while making the
metadata accessible to interested clients. (I&amp;#39;d love opinions on whether this
is better or worse overall.)&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="c1"&gt;// If the callback only accepts a single parameter, Javascript will silently&lt;/span&gt;
&lt;span class="c1"&gt;// ignore the headers object. If the callback function accepts two parameters,&lt;/span&gt;
&lt;span class="c1"&gt;// but the headers aren&amp;#39;t passed, Javascript will pass `undefined` instead.&lt;/span&gt;
&lt;span class="nx"&gt;callbackFunction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="cm"&gt;/* JSON */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* HEADERS */&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Other client environments may have similar difficulties retrieving the response
headers. Given that I&amp;#39;m less familiar with those environments, and that we&amp;#39;ve
produced two distinct viable workarounds for this case, I&amp;#39;m reasonably
confident that the concern can be ameliorated.&lt;/p&gt;

&lt;p&gt;The other major concern with this approach would be how related resources could
be linked to. Self-linking is easy, as are links to other collections of
similarly represented data.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;close&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users?offset=0&amp;gt;;  rel=&amp;quot;first&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users?offset=0&amp;gt;;  rel=&amp;quot;prev&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users?offset=10&amp;gt;; rel=&amp;quot;self&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users?offset=20&amp;gt;; rel=&amp;quot;next&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Any-to-One Relationships are also reasonably easy to specify, but getting
meaningful semantics into place can prove a little trickier.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;close&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;quot;Fully standards compliant, but useless.&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1&amp;gt;; rel=&amp;quot;related&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;Using custom relationships, we get a bit closer.&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1&amp;gt;; rel=&amp;quot;http://example.net/relation/owner&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;Using custom Link parameters; permitted, not well documented.&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1&amp;gt;; rel=&amp;quot;related&amp;quot;; name=&amp;quot;owner&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Any-to-Many Relationships face similar difficulties, but with an added
complication: a mapping needs to be created between the Link header and the
representation.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;close&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/1&amp;gt;; rel=&amp;quot;item&amp;quot;; name=&amp;quot;user&amp;quot;; index=&amp;quot;0&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/5&amp;gt;; rel=&amp;quot;item&amp;quot;; name=&amp;quot;user&amp;quot;; index=&amp;quot;1&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/8&amp;gt;; rel=&amp;quot;item&amp;quot;; name=&amp;quot;user&amp;quot;; index=&amp;quot;2&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;/users/20&amp;gt;; rel=&amp;quot;item&amp;quot;; name=&amp;quot;user&amp;quot;; index=&amp;quot;99&amp;quot;&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;books&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Foundation&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Foundation and Empire&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Second Foundation&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Final Destination&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aside from being an undesirably complex solution, this also has the potential
to cause trouble with web servers and proxies that put heavy restrictions on
header count and length. In addition, there&amp;#39;s a quite a bit of duplication
involved here, which can be costly.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/rfc6570"&gt;URI Templates&lt;/a&gt; give us a way to address some of that duplication,
if we&amp;#39;re willing to accept cooperation between the data model and the metadata.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="http"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;close&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;The Link header specification says that the value in the angle brackets&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;must be a valid URI Reference, meaning that we can&amp;#39;t simply do this:&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="l"&gt;Link: &amp;lt;/users/{id}&amp;gt;; rel=&amp;quot;item&amp;quot;; name=&amp;quot;book&amp;quot;; collection=&amp;quot;books&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;Instead, we can get away with this:&lt;/span&gt;
&lt;span class="na"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;&amp;lt;&amp;gt;; rel=&amp;quot;item&amp;quot;; name=&amp;quot;book&amp;quot;; collection=&amp;quot;books&amp;quot;; template=&amp;quot;/users/{id}&amp;quot;&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;books&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Foundation&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Foundation and Empire&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Second Foundation&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Final Destination&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The headers provide enough information to construct valid URIs for each
collection member, without the overhead of repeating the information for each
item (in either the headers or the data).&lt;/p&gt;

&lt;h4&gt;Final Thoughts&lt;/h4&gt;

&lt;p&gt;For my own purposes, I could abide using HAL, but the Link headers approach
feels much more generally appropriate. The existence of formally defined &lt;code&gt;item&lt;/code&gt;
and &lt;code&gt;collection&lt;/code&gt; relation types indicates that some thought has been applied in
this area, but I&amp;#39;ve found very little information about putting it into active
practice. I may build a prototype API using the Link headers if the idea doesn&amp;#39;t
seem completely broken.&lt;/p&gt;

&lt;p&gt;I would appreciate feedback on any part of this, particularly with an eye
towards building a generally useful recommendation for adding hypermedia links
to today&amp;#39;s (and tomorrow&amp;#39;s) REST interfaces.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>
