REST-based service design, v2

I want to revisit the basic “favorite food” service from last post, in light of some further discussion I’ve had with colleagues.

  • http://host/path/{userid}/favorites

    • GET: returns a list of the user’s favorite foods, in some representation. Returns 404 NOT FOUND if the user has never specified favorites.
    • PUT: sets the list of the user’s favorite foods to be the value sent, creating it if necessary.
    • DELETE: removes the user’s favorite list. This is different than doing a PUT with an empty list.
    • POST: returns 405 METHOD NOT ALLOWED.
  • http://host/path/{userid}/favorites/{food}

    • GET: returns 200 OK if the food is a favorite of the user. Returns 404 NOT FOUND if the food is not a favorite of the user.
    • PUT: makes the food one of the user’s favorites
    • DELETE: makes the food not a favorite
    • POST: returns 405 METHOD NOT ALLOWED

So, PUT can create a resource if it doesn’t exist, and DELETE of a URI means the next GET of it (in the absence of any other operations) will be a 404 NOT FOUND.

One note is that as a client of this API, I want and can make use of the most atomic operation available. For example, to make “spaghetti” a favorite food, I could either:

  1. GET http://host/path/{userid}/favorites
  2. PUT http://host/path/{userid}/favorites (new list with spaghetti added in)

or I could just:

  1. PUT http://host/path/{userid}/favorites/spaghetti

Note that in the first case, I might have an atomicity issue in the presence of concurrent access, so I might need to build in some sort of optimistic locking protocol, where the representation of the favorites list has a version number on it that is checked by the PUT operation. However, if I just use the second method, I don’t have this issue, because the server handles all my concurrency/transactional stuff for me.