Protocol Versioning...

16 views
Skip to first unread message

James Snell

unread,
Feb 3, 2012, 2:48:22 PM2/3/12
to OpenSocial
I'm still in the process of writing this up, below is a very rough first draft.

The high points are this:

1. The use of the a version identifier within the the URI is a useful
convention in some cases but does not fully address all the issues.
There are real practical reasons for following the convention, but
there is extremely little value in mandating the convention or
directly prescribing it's use.

2. The header approach is valid, but creation of a new header field is
not required. I propose that a Link header with rel="implements"
pointing to the version of the specification implemented is more than
sufficient.

3. Indicating the version in use is only part of the problem. We need
to clearly deal with the upgrade transition, and how to signal to the
client that an upgrade is required. There are several possible
approaches:
a. "Hard Upgrade" -- basically, reject down-level requests with an
error response
b. "In Place Upgrade" -- attempt to handle protocol upgrade
in-place and as transparently as possible
c. "Upgrade Redirection" -- attempt to redirect clients to new the version

4. Several mechanisms have emerged recently (Link and Prefer headers)
that, when used with mechanisms that already exist within HTTP
(Upgrade, 426 responses, etc) can provide a generalizable
non-opensocial specific solution to what is a common, non-opensocial
specific problem.

=================
(pay no attention to the section numbers for now)

5.0 Versioning

The ability for server and client implementions to clearly
communicate which version of the OpenSocial specification a
particular Service API and resource supports is critical.

For the purpose of clearly identifying which version of the
OpenSocial specification a particular application is implementing, a
Web Link header referencing the base URI of the OpenSocial
specification and using a rel attribute value of "implements" SHOULD
be included within the HTTP request and response message.

For example, the Link would appear within the request:

GET /api/people/@me/@self HTTP/1.1
Host: example.org
Link: <http://opensocial.org/specs/3.0>; rel="implements"

And within the response:

HTTP/1.1 200 OK
Link: <http://opensocial.org/specs/3.0>; rel="implements"

A server MAY choose to implement additional conventions for
identifying the current version, such as including a version
indicator within the base URI of the Service API (e.g.
http://example.org/v3/api/people). Such conventions are considered
out of scope.

5.1. Upgrade Indication and Transition

When a server implementation of an older version of the OpenSocial
specification upgrades to a newer version, it has the responsibility
to provide a clear mechanism for either continuing to support client
applications using the old version or help clients migrate to the
new.

Whether a server chooses to continue to support the old and new
versions of the OpenSocial specification simultaneously is an
implementation and business decision that is out of the scope of this
specification.

However, when a server wishes to indicate to a client application
that the server has been upgraded and that the old version of the API
is no longer available, it SHOULD do so using an Upgrade Required
response.

An "Upgrade Required Response" is an HTTP response that uses the 426
Upgrade Required status along with an "implements" Web Link. For
instance:

HTTP/1.1 426 Upgrade Required
Upgrade: OpenSocial/3.0
Connection: upgrade
Link: <http://opensocial.org/specs/3.0>; rel="implements"

Use of the 426 Upgrade Required response implies a complete cutover
from one version of the specification to another. Alternatively, a
server can choose to migrate client applications incrementally,
initially deploying the new version of the application side-by-side
with the old. Such a transition may or may not occur "in place",
that is, requiring changes to the URI's a client uses to access the
service.

For example, if a server currently exposes version 3.0 of the
OpenSocial Profile Service at the URI
"http://example.org/api/people", and it wishes to upgrade clients to
a hypothetical version 3.1 in the future, without requiring clients
to change the URIs they use to access the service, it can either
continue to support the 3.0 clients transparently or perform an "in
place" upgrade.

An example 3.0 client request:

GET /api/people/@me/@self HTTP/1.1
Link: <http://opensocial.org/specs/3.0>; rel="implements"

A server implementing the hypothetical 3.1 version of the OpenSocial
spec can continue to respond as if it was a 3.0 implementation:

HTTP/1.1 200 OK
Link: <http://opensocial.org/specs/3.0>; rel="implements"
Content-Type: application/json

{... OpenSocial 3.0 data ...}


Or, it can perform an "in-place" upgrade:

HTTP/1.1 200 OK
Upgrade: OpenSocial/3.1
Connection: upgrade
Link: <http://opensocial.org/specs/3.1>; rel="implements"
Content-Type: application/json

{... OpenSocial 3.1 data ...}

Alternatively, the server MAY choose to deploy the new version with a
new URI.

An example 3.0 client request:

GET /v3.0/api/people/@me/@self HTTP/1.1
Link: <http://opensocial.org/specs/3.0>; rel="implements"

An upgrade redirection from the server:

HTTP/1.1 301 Moved Permanently
Location: /v3.1/api/people/@me/@self HTTP/1.1
Upgrade: OpenSocial/3.1
Connection: upgrade
Link: <http://opensocial.org/specs/3.1>; rel="implements"

5.2. Client Upgrade Preferences

Implementors of client applications MAY use the Prefer HTTP Header
[TODO: Prefer Reference] within a request to indicate the preferred
mechanism for upgrade handling.

This specification registers the following new Prefer header token
values:

return-upgrade-required Indicates that the client prefers the server
to respond with a 426 Upgrade Required response when a protocol
upgrade is required by the server.

upgrade-in-place Indicates that the client prefers the server to
attempt an in-place, transparent upgrade to a newer version of the
protocol, as required. The in-place-upgrade preference MAY
include a preference value indicating the maximum allowed protocol
version. The asterisk (*) character may be used as a wildcard.
For instance, "Prefer: upgrade-in-place=3.*" indicates that the
client prefers an in-place-upgrade for any protocol version
matching the pattern "3.*" (e.g. 3.1, 3.2, 3.3, etc).

upgrade-redirect Indicates that the client prefers the server to use
redirects when upgrading protocols. If a redirect is not
available, then the 426 Upgrade Required response is prefered.

These Preference tokens MAY be used together.

For example, a client can indicate to the server that it is capable
of handling automatic in-place upgrade for any 3.* version of the
specification but prefers use of the 426 Upgrade Required response
for all other cases:

GET /api/people/@me/@self HTTP/1.1
Link: <http://opensocial.org/specs/3.1>; rel="implements"
Prefer: return-upgrade-required, upgrade-in-place=3.*

Or, a client can indicate that is is capable of handling automatic
in-place upgrades for any 3.* version and prefers use of redirects
for all other cases:

GET /api/people/@me/@self HTTP/1.1
Link: <http://opensocial.org/specs/3.1>; rel="implements"
Prefer: upgrade-redirect, upgrade-in-place=3.*

Ryan Baxter

unread,
Feb 5, 2012, 11:48:16 AM2/5/12
to OpenSocial and Gadgets Specification Discussion
Still trying to digest most of this but one thought I had while I was
reading through this was why not have REST APIs without the version in
them point to the latest version of the API that server supports. If
applications want to use a specific version (is the server supports
it) than have them specify that version in the URL.

For example if 3.1 is the latest version the server supports than
http://example.org/api/people would point to the 3.1 version of the
people APIs. It would be equivalent to http://example.org/v3.1/api/people.
If the application wanted to use 3.0 they would have to use
http://example.org/v3/api/people.

Matthew Marum

unread,
Feb 5, 2012, 2:38:10 PM2/5/12
to opensocial-an...@googlegroups.com
My issue with doing that is migration.  Once the server upgrades to a newer version then all the clients who didn't include version numbers in their requests are immediately broken.  We can say "Shame on you!" for not including version numbers, but we should avoid surprising clients like that unless we need them upgrading ASAP.  But the reality is that consumers often have very good reasons for lagging behind.  Upgrading to a newer version of an API is often a lot more work than tweaking the version number on your requests.

Matt Marum


--
You received this message because you are subscribed to the Google Groups "OpenSocial and Gadgets Specification Discussion" group.
To post to this group, send email to opensocial-an...@googlegroups.com.
To unsubscribe from this group, send email to opensocial-and-gadg...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/opensocial-and-gadgets-spec?hl=en.


James Snell

unread,
Feb 5, 2012, 4:36:43 PM2/5/12
to opensocial-an...@googlegroups.com
Matthew,

How is that any different than what we have today? Currently, neither
the client or the server specify what they're implementing so if
anyone changes anything, everyone is gonna get surprised.

The model that I describe draws out a very explicit migration roadmap.

1. Both clients and servers declare explicitly what version(s) of the
spec they implement, on a per-request/response basis.
2. If the client sends a request to the server that either specifies
the wrong version or no version, the server can choose to respond:
a. Like it does today with a best guess
b. With an 426 Upgrade Required response telling the client
exactly which version needs to be implemented.
c. Attempt an in-line upgrade by processing the request and
including an Upgrade/Implements Link in the response
d. Attempt an upgrade redirection by pointing the client at a new
location that supports the new protocol
3. Clients would be able to indicate their preference for which
upgrade behavior to implement using the optional Prefer header.

That's a hell of a lot better than what we have today which consists
mostly of tightly coupling the client and server and hoping for the
best. Clients that implement 3.x or higher would know to include the
version information and prefer in the request. Clients that don't
specify the version information in the request could be assumed to be
using the pre-3.x API... servers can act accordingly from there.

- James

Matthew Marum

unread,
Feb 6, 2012, 8:54:44 AM2/6/12
to opensocial-an...@googlegroups.com
On Sun, Feb 5, 2012 at 4:36 PM, James Snell <jas...@gmail.com> wrote:
Matthew,

How is that any different than what we have today? Currently, neither
the client or the server specify what they're implementing so if
anyone changes anything, everyone is gonna get surprised.


Yes, that's why we need versioning.

Niels van Dijk

unread,
Feb 6, 2012, 5:17:52 PM2/6/12
to opensocial-an...@googlegroups.com
+1

James Snell

unread,
Feb 6, 2012, 6:12:30 PM2/6/12
to opensocial-an...@googlegroups.com

Ok, then perhaps I just missed something in what you and Ryan were saying with regards to my proposal.

--

Ryan Baxter

unread,
Feb 6, 2012, 8:45:12 PM2/6/12
to OpenSocial and Gadgets Specification Discussion
No I think you were on point James.

I like the option for no version numbers because apps we have today
wont break and its just simpler. If I am a gadget developer I not
only need to read the spec, but I need to read the server
documentation to figure out what is supported. While, if I just hit a
URL without a version number in it I don't necessarily need to know
anything about the server. Granted as my application moves from a
prototype stage to production stage I will need to understand what
exactly my app will be using. Plus version numbers may make my app
less portable. If one server supports 2.x but not 3.x and the URLs I
am using are 3.x my app pretty much breaks. Where if I use a URL
without a version I may be able to code to lowest common properties to
make my app work across different versions.

On Feb 6, 6:12 pm, James Snell <jasn...@gmail.com> wrote:
> Ok, then perhaps I just missed something in what you and Ryan were saying
> with regards to my proposal.
> On Feb 6, 2012 5:55 AM, "Matthew Marum" <mgma...@gmail.com> wrote:

Matthew Marum

unread,
Feb 6, 2012, 10:10:26 PM2/6/12
to opensocial-an...@googlegroups.com
So I follow the ease of use argument.  I'd be Ok with allowing versionless API requests to use the latest.  But as you alluded, you can't really deploy Apps like that unless there is a contract that the behavior of existing API will never change.  That would really tie our hands from the spec perspective.  Apps often have legitimate reasons to appeal to the lowest common denominator, but I think we need to retain right to make changes to API behavior.

With versioning developers can still use older API versions while making it easier for those Apps to adopt new API safely.  You can use new API on some requests where it makes sense (or when available) while leaving the majority of your code base on an older version.  Adding versioning is a clean way to get App developers precisely that level of granularity.

Matt

James Snell

unread,
Feb 6, 2012, 10:17:46 PM2/6/12
to opensocial-an...@googlegroups.com
I don't think anyone is suggesting that the apis can never change. The
trick here is making such changes more explicit and noticeable so no
one gets caught by surprise. My suggestion of using something like the
"implements" link in the header of the request/responses, in
combination with the Upgrade and Prefer headers is a step in the
direction of making change as unsurprising as possible... it also
allows an implementation the flexibility of supporting different
versions on a request-by-request or endpoint-by-endpoint basis without
requiring a complete switchover to the a new, and potentially
incompatible spec.

Bastian Hofmann

unread,
Feb 7, 2012, 5:18:48 AM2/7/12
to opensocial-an...@googlegroups.com
Hi,

just cross-posting this from the other api versioning thread:

if we want to version the rest api, we should do it by HTTP headers
and not by some url prefixes. E.g. the "Accept"
header, which was meant to be used for versioning :)

http://barelyenough.org/blog/2008/05/versioning-rest-web-services/

--- Bastian

Laurent-Walter Goix

unread,
Feb 7, 2012, 6:21:51 PM2/7/12
to OpenSocial and Gadgets Specification Discussion
as additional input to this thread, may the "discovery" process help
here? i am thinking in particular at XRD (current opensocial discovery
is still referring to the "old" xrds and do not seem widely used). in
other terms based on my user identity and/or opensocial container
domain clients may discover the different base paths of the single
services, including which service is supported and its version, either
by using the "implements" link rel, by getting it from the service
endpoint url or any other similar mean...

walter

On Feb 7, 11:18 am, Bastian Hofmann <bashofm...@googlemail.com> wrote:
> Hi,
>
> just cross-posting this from the other api versioning thread:
>
> if we want to version the rest api, we should do it by HTTP headers
> and not by some url prefixes. E.g.  the "Accept"
> header, which was meant to be used for versioning :)
>
> http://barelyenough.org/blog/2008/05/versioning-rest-web-services/
>
> --- Bastian
>
>
>
>
>
>
>
> On Tue, Feb 7, 2012 at 4:17 AM, James Snell <jasn...@gmail.com> wrote:
> > I don't think anyone is suggesting that the apis can never change. The
> > trick here is making such changes more explicit and noticeable so no
> > one gets caught by surprise. My suggestion of using something like the
> > "implements" link in the header of the request/responses, in
> > combination with the Upgrade and Prefer headers is a step in the
> > direction of making change as unsurprising as possible... it also
> > allows an implementation the flexibility of supporting different
> > versions on a request-by-request or endpoint-by-endpoint basis without
> > requiring a complete switchover to the a new, and potentially
> > incompatible spec.
>
> > On Mon, Feb 6, 2012 at 7:10 PM, Matthew Marum <mgma...@gmail.com> wrote:
> >> So I follow the ease of use argument.  I'd be Ok with allowing versionless
> >> API requests to use the latest.  But as you alluded, you can't really deploy
> >> Apps like that unless there is a contract that the behavior of existing API
> >> will never change.  That would really tie our hands from the spec
> >> perspective.  Apps often have legitimate reasons to appeal to the lowest
> >> common denominator, but I think we need to retain right to make changes to
> >> API behavior.
>
> >> With versioning developers can still use older API versions while making it
> >> easier for those Apps to adopt new API safely.  You can use new API on some
> >> requests where it makes sense (or when available) while leaving the majority
> >> of your code base on an older version.  Adding versioning is a clean way to
> >> get App developers precisely that level of granularity.
>
> >> Matt
>

James Snell

unread,
Feb 7, 2012, 6:55:05 PM2/7/12
to opensocial-an...@googlegroups.com
Absolutely, the discovery mechanism definitely plays a role in proper
handling of the versioning, particularly from a purely REST/HATEOS
point of view. The application needs to be able to reasonably discover
which version the specification a server supports. Personally, I have
significant concerns over the continued use of XRD here but that's for
a much later discussion.

James M Snell

unread,
Feb 9, 2012, 10:49:28 PM2/9/12
to opensocial-an...@googlegroups.com
Ok, the beginning run at the versioning stuff has been added to the wiki:

http://docs.opensocial.org/display/OSD/Protocol+and+Data+Model+Versioning

Reply all
Reply to author
Forward
0 new messages