1

The FooBar Api is Published

Let's say there's a team of developers working on an API, called the FooBar api with a few endpoints:

GET /foo
    # returns {'bar': '/bar', 'data': 'foo'}

GET /bar
    # returns {'data': 'hello world!'}

Now, let's say the FooBar api exploded and became hugely popular. Developers from all around the world are using the FooBar api and now thousands of projects are completely dependent on it.


The Problem

The FooBar api recently got a new project manager. He says, that it is now desired that the responses return a message instead of data, because message is "more descriptive." Unfortunately, any change to the FooBar API could break thousands of these projects. Even though all of these developers whose projects were broken would mostly be patient and understanding about the change, the FooBar team doesn't want to break their own dependent projects and decide it's best to keep the api backwards compatible.


The Solution

The FooBar api needs to be versioned. Unfortunately there is no good way to do this. Luckily for the FooBar team, their project manager knows best and decided that the versioning should be accomplished by placing a version number in the url since "that's the part he can see." So, once the second version of the FooBar api is complete, the two versions should look something like this:

FooBar v1
GET /foo
    # returns {'bar': '/bar', 'data': 'foo'}

GET /bar
    # returns {'data': 'hello world!'}

FooBar v2
GET /v2/foo
    # returns {'bar': '<url to bar>', 'message': 'foo'}

GET /v2/bar
    # returns {'message': 'hello world!'}

The Second Problem

The FooBar team has another problem now; they don't know what should go in <url to bar>. Of the roughly infinite possible permutations of characters, they were impressively able to get it down to two choices - /v2/bar and /bar.


The Question

What are the pro's and cons of using /v2/bar vs /bar?

Community
  • 1
  • 1
Phillip Martin
  • 1,910
  • 15
  • 30
  • 1
    If `/foo` is not changing, then why publish a `/v2` route for it? – OneCricketeer Jul 25 '16 at 22:35
  • @cricket_007 In this example I published a `/v2` route for `/foo` for Illustration purposes. I'm interested in knowing how url's should be constructed for a `v2` response. Since you bring up a good point, I'm going to change the example to demonstrate that a `v2` route should definitely be published for `/foo`. – Phillip Martin Jul 26 '16 at 01:04

1 Answers1

4

Do neither. It's not in keeping with REST or HTTP to have two different representations of the same resource with different URLs. They are the same resource, they should have the same URL.

Whether the clients are using version 1 of the API or version 2 of the API, they are still referring to the same resource, they just want different representations of it. So get rid of /v2/ in your URLs altogether and have your clients ask for the version they want as a media type parameter:

GET /foo HTTP/1.1
Accept: application/vnd.whatever+json;version=2
Connection: close

Your existing clients won't provide the version parameter and you can default to version 1. Newer clients that support version 2 of the API will know to ask for the version 2 representation of that resource. Your links can refer to the same resource properly regardless of which version of the API the client is using.

Jim
  • 72,985
  • 14
  • 101
  • 108
  • 1
    Thanks for trying to help. You're solution is great - there's no need to quibble with the url at all! Unfortunately, I need to work under the assumption that versioning is done through the url. – Phillip Martin Jul 26 '16 at 01:58
  • Any help on how to process the version from the Accept header in Flask? – Nicholas Tulach Feb 15 '17 at 18:44
  • Split the string on `';'` and check the media type matches, e.g. `media_type, *params = header.split(';')`. Then map the parameters into a dictionary and get the version, e.g. `dict(map(lambda item: item.split('='), params)).get('version', 1)` – Jim Feb 16 '17 at 00:27