<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Peter Williams &#187; rest-versioning</title>
	<atom:link href="http://barelyenough.org/blog/tag/rest-versioning/feed/" rel="self" type="application/rss+xml" />
	<link>http://barelyenough.org</link>
	<description>… and there is much to be learned</description>
	<lastBuildDate>Mon, 19 Jul 2010 14:57:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>REST/HTTP Service Versioning (Response to Jean-Jacques Dubray)</title>
		<link>http://barelyenough.org/blog/2008/05/resthttp-service-versioning-reponse-to-jean-jacques-dubray/</link>
		<comments>http://barelyenough.org/blog/2008/05/resthttp-service-versioning-reponse-to-jean-jacques-dubray/#comments</comments>
		<pubDate>Mon, 19 May 2008 05:54:39 +0000</pubDate>
		<dc:creator>Peter Williams</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[rest-versioning]]></category>

		<guid isPermaLink="false">http://pezra.barelyenough.org/blog/?p=341</guid>
		<description><![CDATA[ Jean-Jacques Dubray takes issue with 
my approach of using content negotiation to manage service versioning in HTTP.  I actually hesitate to
respond to Mr. Dubray because the overall tone of his piece is rather
off putting. On the other hand, he raises a couple of interesting
questions which I have been really looking for and excuse to [...] ]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ebpml.org/blog/89.htm">Jean-Jacques Dubray takes issue</a> with 
<a href="http://pezra.barelyenough.org/blog/2008/05/versioning-rest-web-services/">my approach of using content negotiation to manage service versioning</a> in HTTP.  I actually hesitate to
respond to Mr. Dubray because the overall tone of his piece is rather
off putting. On the other hand, he raises a couple of interesting
questions which I have been really looking for and excuse to talk
about.  So I will give it a go.</p>

<h3>Handling obsolescent service providers</h3>

<p>Mr. Dubray asks how we deal with version skew between the client and
server.</p>

<blockquote>
  <p>Backwards compatibility is when the consumer comes in with a &#8220;newer&#8221;
  request version than the service provider can provide. This is
  common when a consumer uses different providers for the same type of
  service. So ultimately, you need to provide some room to define the
  version of both the consumer and the version of the service provider
  that it is targeting. Your mechanism only supports &#8220;one version&#8221;.</p>
</blockquote>

<p>Not true, the versioning mechanism I describe easily handles multiple
versions.  First, lets be clear, a service provider cannot provide
capabilities that where not conceived of until after it was written.
So Mr. Dubray must be interested in is the ability of a single
consumer to successfully communicate with multiple versions of the
service provider.  I agree with him that this is an absolutely vital
feature of any versioning mechanism.</p>

<p>Fortunately, content negotiation deals with this issue quite handily.
I left this out of the original post for simplicities sake but it well
worth talking about.  HTTP allows user agents &#8212; or service consumers,
if you prefer &#8212; to specify more than one acceptable response format.
For example, the following is a perfectly legal HTTP conversation.</p>

<pre><code>===&gt;
GET /accounts/42
Accept: application/vnd.myapp-v2+xml, application/vnd.myapp-v1+xml;q=0.8

&lt;===
200 OK
Content-Type: application/vnd.myapp-v1+xml

&lt;account&gt;
  &lt;name&gt;Inigo Montoya&lt;/name&gt;
&lt;/account&gt;
</code></pre>

<p>The <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">Accept header field</a> in the request indicates that the consumer
can operate using either version 1 or 2 of the API but it prefers
version 2.  Accept headers can include any number of MIME media types
along with preference indicators (the q=number part).  This allows
consumers to inform the server of all acceptable dialects of the API
with which it can work.  In the example, the server obviously did not
support version 2 of the API and therefore responded using version 1.</p>

<h3>Resource deprecation</h3>

<p>Further along Mr. Dubray asks this question,</p>

<blockquote>
  <p>Another flaw of your versioning strategy is that URIs are by default
  part of the versioning strategy. I have often pointed out that
  &#8220;Query-by-examples&#8221; are encoded by members of the REST community
  (MORCs) in a URI syntax, for instance:</p>

<pre><code>/customer/{id}/PurchaseOrders ...
</code></pre>
  
  <p>Peter, how do you express that a particular QBE belongs to one
  version and not to the other?</p>
</blockquote>

<p>I don&#8217;t.  The set of purchase orders associated with a particular
customer is not version specific.  The customer has agreed to purchase
the same things regardless of which version of the service you are
talking to.</p>

<p>Perhaps the question Mr. Dubray is really trying to ask is, what
happens if you want to deprecate such resource?</p>

<p>(One reason to do so
might be that the purchase order collections become too big to
reasonably render in a single response.  There are other, better ways
to solve that particular problem but it is a nice concrete use case for
resource deprecation.)</p>

<p>Resource deprecations is easily handled in REST using media types to
handle versioning.  First some ground rules, user agents should
<em>never</em> be constructing such a URI.  Doing so should be a gross
violation of the HATEOAS constraint of REST.  Rather they would be
extracting that URI from the representation of the customer provided
by the server.  In such a case, an HTTP conversation getting the
purchase orders for a customer might look like this.</p>

<pre><code>===&gt;
GET /customer/42
Accept: application/vnd.myapp-v1+xml
&lt;===
200 OK
Content-Type: application/vnd.myapp-v1+xml

&lt;customer&gt;
  &lt;purchase-orders href="http://service.example/customer/42/purchase-orders"/&gt;
&lt;/customer&gt;


===&gt;
GET /customer/42/purchase-orders
Accept: application/vnd.myapp-v1+xml
&lt;===
200 OK    
Content-Type: application/vnd.myapp-v1+xml

&lt;purchase-orders&gt;
  ...
&lt;/purchase-orders&gt;
</code></pre>

<p>At version 2 of the API we deprecate the
all-purchase-orders-for-customer resource &#8212; removing all references to it in
the customer representations &#8212; and replace it with a
purchases-order-by-month-by-customer resource.  A similar HTTP
conversation with a client capable of handling version 2 of the API
would look like this.</p>

<pre><code>===&gt;
GET /customer/42
Accept: application/vnd.myapp-v2+xml
&lt;===
200 OK
Content-Type: application/vnd.myapp-v2+xml

&lt;customer&gt;
  &lt;purchase-orders-by-month href-template="http://service.example/customer/42/purchase-orders?in_month={xmlschema-gYearMonth}"/&gt;
&lt;/customer&gt;


===&gt;
GET /customer/42/purchase-orders?in_month=2008-05
Accept: application/vnd.myapp-v2+xml
&lt;===
200 OK    
Content-Type: application/vnd.myapp-v2+xml

&lt;purchase-orders&gt;
  ...
&lt;/purchase-orders&gt;
</code></pre>

<p>Notice that in version 2 of the API the
all-purchase-orders-for-customer resource is no longer exposed in any
way.  As a human you might guess that it still exists, and indeed it
would need to in order to handle requests to version 1 of the API.
However, a version 2 consumer will never make a request to that
resource because it is not mentioned in the version 2 representations.
Indeed, any requests for the all-purchase-orders-for-customer by a
version 2 consumer would be met with a <code>406 Not Acceptable</code> response
because it is not part of the version 2 API.</p>

<h3>Wrap up</h3>

<p>Toward the end Mr. Dubray gets into full rant mode with these bits,</p>

<blockquote>
  <p>You will soon start realizing that resources do have a state that is
  independent of the &#8220;application&#8221; since by definition a resource can
  participate in multiple &#8220;applications&#8221;. This is the essence of SOA,
  i.e. the essence of reuse.</p>
</blockquote>

<p>Resources certainly may participate in multiple &#8220;applications&#8221;.  There
is nothing in the REST principles that prevent that.  I don&#8217;t really
claim to be an SOA expert.  I just make systems work using REST
principles.  So far I have not found a problem reusing my resources in
multiple applications.  In fact, REST seems to excel at that very
thing.</p>

<blockquote>
  <p>At least, some of the MORCs [Member Of the REST Community] could
  have the courtesy to acknowledge that they are indeed building a
  programming model on top of REST, that this programming model needs
  clear semantics and that these semantics are not intrinsically part
  of REST (nor always RESTful).</p>
</blockquote>

<p>I, for one, will readily acknowledge that we have built, and are
continuing to build, programming models on top of REST.  REST is
merely a set of principles, articulated as constraints, that
facilitate the creation of useful network based architectures.  I
would be very surprised if many in the REST community would disagree
with me.  These programming models do, for the most part, adhere to
the REST principles.</p>

<p>Building REST/HTTP web services is certainly not fully understood yet.
That does not make it special, hardly any sort of system design or
architecture is fully understood.  However, REST seems, to me at
least, to be a better fit for today&#8217;s applications and technologies
than any of the alternatives.</p>


<hr />


<h4>Related Posts</h4>

<p>If you&#8217;re interested in REST/HTTP service versioning be sure not to miss the <a href="/blog/tag/rest-versioning/">rest of the series.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://barelyenough.org/blog/2008/05/resthttp-service-versioning-reponse-to-jean-jacques-dubray/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Versioning REST Web Services (Tricks and Tips)</title>
		<link>http://barelyenough.org/blog/2008/05/versioning-rest-web-services-tricks-and-tips/</link>
		<comments>http://barelyenough.org/blog/2008/05/versioning-rest-web-services-tricks-and-tips/#comments</comments>
		<pubDate>Tue, 13 May 2008 20:47:56 +0000</pubDate>
		<dc:creator>Peter Williams</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[rest-versioning]]></category>

		<guid isPermaLink="false">http://pezra.barelyenough.org/blog/?p=336</guid>
		<description><![CDATA[ In my previous post on this subject I described an approach
to versioning the API of a REST/HTTP web service.  This approach has
significant advantages over the approach that is currently most common
(i.e. embedding a version token in the URL).  However, it does have
some downsides.  This post is an attempt to outline those and [...] ]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://pezra.barelyenough.org/blog/2008/05/versioning-rest-web-services/">previous post on this subject</a> I described an approach
to versioning the API of a REST/HTTP web service.  This approach has
significant advantages over the approach that is currently most common
(i.e. embedding a version token in the URL).  However, it does have
some downsides.  This post is an attempt to outline those and to
present some ways to mitigate the negative impacts.</p>

<h3>Nonstandard MIME media types</h3>

<p>Using content negotiation to manage versions requires, by definition,
the introduction of nonstandard media types.  There is really no way
around this.  I personally don&#8217;t feel this is a Bad Thing.  The
new, nonstandard, media types do a much better job describing the sort
of media the client is requesting.  It does, however, mean that
browsers &#8212; and perhaps some HTTP tools &#8212; will work less well with
the web service.</p>

<p>The browser not working is a pretty big issue.  They are almost
certainly not the target consumer of the services, but having the
browser not work raises the level of effort for exploring the API.  If
you have created a cool new service you want as few barriers to entry
as possible.  Personally, I always use <a href="#curl">curl</a> when I am
exploring but I know several people who would prefer to use a browser.</p>

<p>Unfortunately, I don&#8217;t really have a great general solution for
browsers.  That being said, in many situations a much can be done to
make life better.  For example, if the resources in question do not
have HTML representations you could serve the current preferred format
with a generic content type that browsers can render &#8211;
e.g. <code>text/plain</code> or <code>application/xml</code> &#8212; to browsers.</p>

<h3>Curl <a id="curl"></a></h3>

<p>One advantage of having the version token directly in the URL is that
it makes it <em>really</em> easy to use <a href="http://curl.haxx.se/">curl</a> against the service.  By
default curl makes requests with the Accept header field set to <code>*/*</code>.
For a reasonably designed service this would result in a response in
the current preferred format.  If you want to change to Accept header
you need to invoke curl like this</p>

<pre><code>curl --header 'Accept: application/vnd.foo.myformat-v1+xml' http://api.example/hello-world
</code></pre>

<p>That is not too horrible, really.  It is a bit much to type all the time, but I have curl rc files for all the
formats I deal with on a daily basis.  If your service is
implemented in Rails there is an even easier way.  With Rails you give each
format you support a short name that may be used as an &#8220;extension&#8221; for
URLs.  For example, if we define the short name for
<code>application/vnd.foo.myformat-v1+xml</code> to be <code>mf1</code> we can say this</p>

<pre><code>curl http://api.example/hello-world.mf1
</code></pre>

<p>That is equivalent, from the point of view of a Rails based service,
to the previous example.  I imagine similar functionality could be
implemented in most web frameworks.  This effectively puts you back to
having the version embedded in the URL, which is convenient for
debugging and exploration.  (It is still unsuitable for production
use, though, for all the same reasons as other approaches to embedding
the version in the URL.)</p>

<h3>Nonobviousness</h3>

<p>Another potential downside of using content negotiated versioning is
that the various versions my be less discoverable, compared to a
version-in-the-URL approach.  I am not entirely sure this is true &#8211;
after all there is a version token in the media type &#8212; but if it
is true it would be a Good Thing.</p>

<p>Do you really want people &#8220;discovering&#8221; a version of the API that was
deprecated a year ago?  I think it might be better, in either
approach, to use version tokens that are not readily guessable.
Obviously, previous versions of and API will be documented and remain
accessible, but raising some barriers to entry on depreciated parts of
a system seems appropriate to me.</p>

<h3>Unfamiliarity</h3>

<p>This may be the biggest issue of all.  People are just not very
familiar, and therefore comfortable, with content negotiation.  This
in spite of the fact that it has been a fundamental part of HTTP since
forever.  I think this features obscurity is waning now, though,
because it is such a powerful feature.</p>

<p>Two years ago <a href="http://www.loudthinking.com/arc/000572.html">Rails got content negotiation support</a>.
(That link seems to be broken at the moment.  You can see part of the
post I am talking about by going
<a href="http://www.loudthinking.com/arc/2006_04.html">here</a> and searching for
&#8220;The Accept header&#8221;.)  As frameworks like Rails keep adding and
improving their support for this powerful feature the community of
developers will become more familiar and comfortable with it.  What is
needed now is more education in the community on how best to utilize
this feature.</p>


<hr />


<h4>Related Posts</h4>

<p>If you&#8217;re interested in REST/HTTP service versioning be sure not to miss the <a href="/blog/tag/rest-versioning/">rest of the series.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://barelyenough.org/blog/2008/05/versioning-rest-web-services-tricks-and-tips/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Versioning REST Web Services</title>
		<link>http://barelyenough.org/blog/2008/05/versioning-rest-web-services/</link>
		<comments>http://barelyenough.org/blog/2008/05/versioning-rest-web-services/#comments</comments>
		<pubDate>Mon, 12 May 2008 05:59:37 +0000</pubDate>
		<dc:creator>Peter Williams</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[rest-versioning]]></category>

		<guid isPermaLink="false">http://pezra.barelyenough.org/blog/?p=335</guid>
		<description><![CDATA[ Managing changes to APIs is hard.  That is no surprise to anyone who
has ever maintained an API of any sort.  Web services, being a special
case of API, are susceptible to many of the difficulties around
versioning as other types of APIs.  For HTTP based REST style web
services the combination of resources and content [...] ]]></description>
			<content:encoded><![CDATA[<p>Managing changes to APIs is hard.  That is no surprise to anyone who
has ever maintained an API of any sort.  Web services, being a special
case of API, are susceptible to many of the difficulties around
versioning as other types of APIs.  For HTTP based REST style web
services the combination of resources and content negotiation can be
used to mitigate most of the issues surrounding API versioning.</p>

<p>Let&#8217;s assume you have a REST/HTTP web service that has some account
resources.  Say you can make a request like this:</p>

<pre><code>===&gt;
GET /accounts/3 HTTP/1.1
Accept: application/vnd.mycompany.myapp+xml
&lt;===
HTTP/1.1 200 OK
Content-Type: application/vnd.mycompany.myapp+xml

&lt;account&gt;
  &lt;name&gt;Inigo Montoya&lt;/name&gt;
&lt;/account&gt;
</code></pre>

<p>First, you probably noticed that my example uses a 
<a href="http://tools.ietf.org/html/rfc4288#section-3.2">vendor MIME media type</a> to describe the representation.  Using a
more generic MIME media type like <code>application/xml</code> is much more
common, at least in my experience.  Using generic media types is
perfectly legal but a bit silly.  You are not really asking for any
old XML document, but rather an XML document that has a quite
specific schema.  Aside from my idealistic rantings, using a specific
media type has some strong practical benefits which are at the core of
this post.</p>

<h2>Backwards compatible changes</h2>

<p>Often changes will need to be made to expose new behavior of the
system that do not negatively impact correctly implemented clients.
Say, for example, you want to start tracking email address for
accounts.  If the <code>application/vnd.mycompany.myapp+xml</code> format
documentation is clear that elements that are not recognized should be
ignored you can simply add a email element to the account
representation.</p>

<pre><code>&lt;account&gt;
  &lt;name&gt;Inigo Montoya&lt;/name&gt;
  &lt;email-address&gt;mailto:prepare-to-die@youkilledmyfather.example&lt;/email-address&gt;
&lt;/account&gt;
</code></pre>

<p>Any client that was created before the addition of the email element
will simply ignore it&#8217;s presence.  Problem solved.</p>

<h2>Incompatible changes</h2>

<p>Unfortunately, not all changes can be implemented in a way that is
backwards compatible.  For example, a couple of months after adding
email to accounts the sales team sign a deal for 1 bazillion dollars.
But the new customer demands that each account be allowed to have more
than one email address.  After thinking for a while, you decide that
the best way to expose that is by changing the account representation
as follows.</p>

<pre><code>&lt;account&gt;
  &lt;name&gt;Inigo Montoya&lt;/name&gt;
  &lt;email-addresses&gt;
    &lt;email-address priority='1'&gt;mailto:prepare-to-die@youkilledmyfather.example&lt;/email-address&gt;
    &lt;email-address priority='2'&gt;mailto:vengeance@youkilledmyfather.example&lt;/email-address&gt;
  &lt;email-address&gt;
&lt;/account&gt;
</code></pre>

<p>That, of course, will break any clients that are expecting the old
format &#8212; so pretty much all of them.  This is a place where we can
bring content negotiation to bare.  You can simply define a new media
type &#8212; say <code>application/vnd.mycompany.myapp-v2+xml</code> &#8212; and associate
new multi-email format with it.  Clients can then request whichever
format they want.  Older clients don&#8217;t know the new media type so they
get served the older single email format.</p>

<pre><code>===&gt;
GET /accounts/3 HTTP/1.1
Accept: application/vnd.mycompany.myapp+xml
&lt;===
HTTP/1.1 200 OK
Content-Type: application/vnd.mycompany.myapp+xml

&lt;account&gt;
  &lt;name&gt;Inigo Montoya&lt;/name&gt;
  &lt;email-address&gt;mailto:prepare-to-die@youkilledmyfather.example&lt;/email-address&gt;
&lt;/account&gt;
</code></pre>

<p>Newer clients do know the new media type so they can have access to
the new functionality.</p>

<pre><code>===&gt;
GET /accounts/3 HTTP/1.1
Accept: application/vnd.mycompany.myapp-v2+xml
&lt;===
HTTP/1.1 200 OK
Content-Type: application/vnd.mycompany.myapp-v2+xml

&lt;account&gt;
  &lt;name&gt;Inigo Montoya&lt;/name&gt;
  &lt;email-addresses&gt;
    &lt;email-address priority='1'&gt;mailto:prepare-to-die@youkilledmyfather.example&lt;/email-address&gt;
    &lt;email-address priority='2'&gt;mailto:vengeance@youkilledmyfather.example&lt;/email-address&gt;
  &lt;email-address&gt;
&lt;/account&gt;
</code></pre>

<p>Everyone gets what they need.  Easy as pie.</p>

<h2>Alternate approaches</h2>

<p>The most commonly proposed approach for versioning REST/HTTP web
service interfaces today seems to be to mutilate the URIs by inserting
a version.  For example,</p>

<pre><code>http://foo.example/api/v1/accounts/3
</code></pre>

<p>I really hate this approach as it implies that an account in one
version of the API is really a different resource than the account in
a different version of the API.</p>

<p>It also forces clients into a nasty choice, either support multiple
versions of the API simultaneously or break one of the core constrains
of REST.  For example, say a client exists for the v1 API that saves
references (URIs that include the version indicator) to accounts.
Some time later the client is updated to support the new version of
the API.  In this situation the The client can support both versions
of the API simultaneously because all the previously stored URIs point
at the old version of the API or it has to mung all the URIs it has
stored to the point at the new API.  Munging all the URIS breaks the
<a href="http://pezra.barelyenough.org/blog/2007/05/hypermedia-as-the-engine-of-application-state/">HATEOAS</a> constraint of REST and supporting multiple versions of the API is a maintenance nightmare.</p>

<h2>Conclusion</h2>

<p>Changes to REST/HTTP web service interfaces come it three basic
flavors, changes to the properties associated with a type of resource,
additions of new types of resources and deprecation of obsolete types
of resources.  If you are following the <a href="http://pezra.barelyenough.org/blog/2007/05/hypermedia-as-the-engine-of-application-state/">HATEOAS</a> constraint of REST the
approach described here can be used to safely handle all three scenarios.</p>

<p>This approach does lead to media types being created, but media types
are cheap so we can &#8212; and should &#8212; have as many as we need.  Used
properly, content negotiation can be used to solve the problems
related to versioning a REST/HTTP web service interface.</p>


<hr />


<h4>Related Posts</h4>

<p>If you&#8217;re interested in REST/HTTP service versioning be sure not to miss the <a href="/blog/tag/rest-versioning/">rest of the series.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://barelyenough.org/blog/2008/05/versioning-rest-web-services/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
	</channel>
</rss>
