designing actions in REST API - when is RESTful too RESTful?

Appelsien S. picture Appelsien S. · Jul 15, 2011 · Viewed 12.2k times · Source

I am in the process of designing a REST API for a project we are working on. That is, I am writing the specifications which will be implemented later on.

I am having troubles to think into nouns/resources instead of actions/verbs. Without going into too much project specifics, we are writing an API around SVN. For example, take the action which commits changes to the SVN server. In our project, we have multiple definitions/versions of the commit action:

  • simply commit all changed files
  • commit a list of changed files (a subset, instead of the whole set of changed files)
  • ...

(1) How would you design the URL? The first question is, how do I describe the commit action as a noun/resource instead of a verb?

Some would say:

POST/PUT http://server.com/api/revision/commit

Should it be a POST or a PUT? I am not really creating a commit resource, so it's not a POST. However, I am not really changing a commit resource, so it's not a PUT. Actually, it's not a resource, it's an action. Once the action is executed, it's gone, there is no resource to be created, changed or kept for later reference.

That said, it must be a resource, so the URL should probably be like this

POST http://server.com/api/revision/commitment

It's also a POST, since we are creating a commitment. We are not changing anything, so no PUT. Also note that I changed commit into commitment, to reflect the fact that we are dealing with resources.

Does this make sense? To me it doesn't, it drives me nuts. I want to execute an action, not create a resource which resembles the action. But anyway.

That said, going further, I just created a commitment resource. So logically, I should be able to retrieve it later on:

GET http://server.com/api/revision/commitment/:id

But there is no commitment resource! I was forced to make one in order to be RESTful. head explodes

So, how do you really specify actions on resources in a REST API? I am not talking about the kind of actions which create a resource (create user, ...), but about the kind of actions which manipulate a resource or act on a resource (commit revision, ...).

(2) Then, secondly, in case of the second definition (see above), how do we specify the subset of changed files? Through parameters or in some structure (for example JSON array) in the BODY? Which one is preferred? Are there any general rules?

Thanks all!

Answer

fumanchu picture fumanchu · Jul 15, 2011

Sometimes it's easier to back up in a URL design than go forward. It seems to me like what you're calling a "commitment" is actually a revision itself. svn commit basically means, "please accept these differences from my currently selected revision as a new (child) revision". Therefore, you need to identify that currently selected revision (in order to remain stateless) and then append to it in a meaningful way:

POST http://server.com/api/revisions/16/children/

That is, POST an entity which encapsulates the differences from revision 16. The server could then respond with 201 Created, plus Location: /api/revisions/23/ (or /api/revisions/16/children/1, which redirects to the former).

Then, not only have you provided for the creation of new revisions, but also most likely added a useful list of the direct children of a given revision.