How do I manage updates to resources when users are using the same major (but different minor) versions of my RESTful API?

StackOverflow https://stackoverflow.com/questions/19147143

Question

Imagine the following scenario. I create and release the first version (v1.0) of a Library API for my Library service. It expects all new books to be posted with the following three values:

POST /books HTTP/1.1
Content-Type: application/json
...
{
  "title":"The Life of Beethoven",
  "author":"David Wyn Jones",
  "publisher":"Cambridge University Press"
}

--------
HTTP/1.1 201 Created
Location: http://example.com/books/12345

Several users start using this API. A couple months later, I find that I need to offer users the option to also post the edition if they have that information. So I publish a minor, backwards compatible extension to my API (v1.1), so that the edition attribute is now accepted but still optional. Now Joe, one of my users, can successfully post the following:

PUT /books/12345 HTTP/1.1
Content-Type: application/json
...
{
  "title":"The Life of Beethoven",
  "author":"David Wyn Jones",
  "publisher":"Cambridge University Press",
  "edition":"First"
}

and then have this:

GET /books/12345
Accept: application/json

return:

HTTP/1.1 200 OK
Content-Type: application/json
{
  "title":"The Life of Beethoven",
  "author":"David Wyn Jones",
  "publisher":"Cambridge University Press",
  "edition":"First"
}

Suppose Nancy, however, hasn't upgraded her use of the API to v1.1; she's still on 1.0. As a result, she'd never post a book with its edition information. She'd issue a GET (as above) and have the information, but would be ignored (because she can ignore attributes she does not understand).

However, this all breaks down if Nancy ever needed to retrieve this resource and then update it via her 1.0 API. Her request would look like this:

PUT /books/12345 HTTP/1.1
Content-Type: application/json

{
  "title":"The Life of Beethoven",
  "author":"David Wyn Jones",
  "publisher":"Cambridge University Press"
}

This PUT is supposed to replace the representation of this resource entirely, right? Would that mean that the server is required eliminate the edition attribute entirely, rendering Joe's edition attribute null? Should the server be smart enough to only update attributes or the resource it is provided, or is it the responsibility of the client to pass back attributes it doesn't understand? The former means more work for the server, but the latter means that just one poorly-coded client can screw up server resources for others.

Are there other ways to solve this problem? Have you solved this problem recently, and how did you do it?

Was it helpful?

Solution

If you are trying for a backward compatible server, then I would make the server only remove values when passed a field value that is explicitly null, e.g.

{
  "title":"Fahrenheit 451",
  "author":"Ray Bradbury",
  "publisher":"Penguin",
  "edition": null
}

That way clients coded against the v1.1 API have the ability to explicitly remove that field value, but those targeting v1.0 do not accidentally make changes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top