15

I have a RESTFul server API which I've built. Some parts of it is not controlling resources and I'm having trouble mapping the relevant URL + HTTP-method to the actions that are executed on the server.

e.g. I can backup every resource on the server with POST /backup, but I'm not sure if this the most appropriate mapping. What about a single resource? Should I specify it with: POST /backup/id or by declaring the id as a variable that I send: POST /backup <id>

Please give me some tips on how to structure this most appropriately so that my API is easy to grasp.

Jacob Stevens
  • 854
  • 1
  • 8
  • 17
Niklas
  • 465
  • 2
  • 9
  • 19
  • Are you able to backup different types of resources or just one type? If more than one type then you will need more than just an Id to create a backup. – Raymond Saltrelli May 23 '13 at 15:31

4 Answers4

8

This depends if you create a new backup object on database each time you call, or if you have many backup objects (that is, backups for different files, for example) that hold only the last value.

POST /backups is used to create a new object, and so the correct answer if you always create a new backup.

PUT /backups/id if you are updating your backup data in the same object.

restufull routes

fotanus
  • 19,618
  • 13
  • 77
  • 111
  • 1
    It seems like Niklas' /backup resource is an action resource (_"I can back up every resource...with 'POST /backup'...._"). If so, using 'POST /backups' (plural) makes the purpose a little ambiguous. [Mark Masse recommends](http://www.wrml.org/docs/decks/rest.pdf) action resources be verbs (backup) and collection resources be plural (backups). These semantics aren't yet standardized, but useful to consider. – Jacob Stevens Jun 04 '13 at 02:03
  • @JacobStevens What you say is true and that is a very interesting discussion, yet I can't advise follow a not standardized semantic, because standards are somewhat chaotic, and many times when there is more than one appropriated, ended up by no one being universally adopted and we miss a point of a standard. For now, I believe it is better train yourself to use REST with nouns and watch carefully for changes. – fotanus Jun 04 '13 at 02:44
6

I believe POST /backup (to backup all resources) and POST /backup <id> (to backup a single resource) are going to suit you best here.

CRUD MAPPING: Like Ray said, backup doesn't map to CRUD well; you want an action resource on the server to perform the function. Mark Massé wrote the O'Reilly book on REST API design and his recommendation is to use an action resource on the server in that case (see slide 20 on the Action archetype).

URI DESIGNATION: Action resources should be the last segment of the URI with no child resources. This will make sense when you see the reason below for which HTTP method is best suited here.

HTTP METHOD: Backup shouldn't be an idempotent action, so you want the HTTP method that's not idempotent. That's POST. Not only is PUT idempotent, the URI you specify is where you're putting the resource you're sending. You don't want to do that if you want to be restful. Part of the purpose of POST and its non-idempotence is specified as

providing a block of data, such as the result of submitting a form, to a data-handling process

which is what you want here.

REST: To be a layered system, the server (by way of its action resource (the backup method)) should specify where its output should go; the client shouldn't house that logic.


So, doing it this way, your backup action resource is free to determine where you want to put the backups (which may be a store resource (/backups); see slide 19) and whether you want to overwrite the previous backups or whether you want to implement some form of version control (something that REST design doesn't account for). So basically you were on the right track!

Jacob Stevens
  • 854
  • 1
  • 8
  • 17
  • 1
    I liked your answer but the `his recommendation` link is out of date now; it's not working (404). Can you update your answer? – Tyler Collier May 14 '14 at 22:52
2

While RESTafarians (REST purists) will say that the only actions in a REST API should be the basic CRUD operations that map the HTTP verbs--GET, PUT, POST and DELETE--this sometimes isn't practical and makes your job more difficult than it needs to be. If you want to have other actions, such as Backup, then you might want to consider an RPC-style REST implementation that uses both the HTTP verb and an action name embedded in the request URL to determine the action being performed.

GET    /resource/select
GET    /resource/select?id={id}
PUT    /resource/update?id={id}
POST   /resource/insert
DELETE /resource/delete?id={id}
PUT*   /resource/backup?id={id}
GET    /resource/backup?id={id}

*If your app maintains multiple backups of resources and you want the Backup action to always create a new backup then it it customary to use POST as Backup is not idempotent. If you only maintain one backup and the Backup action simply upserts the backup of the resource then you should use PUT since Backup is idempotent in this case.

Raymond Saltrelli
  • 4,071
  • 2
  • 33
  • 52
  • 4
    The actual REST purists are quite adamant that you should avoid trying to correlate the uniform interface of HTTP and CRUD. – Darrel Miller May 23 '13 at 18:34
0

You could use POST /backups?resource=car&id=123 for backing up the car with id=123 (of course you could pass a JSON object instead of parameters in the URL if you prefer). Note also the plural in backups, it's a detail but it communicates better the fact that one or more backups may be found under this URI.

If you want to replace a previously created backup, then, as others mentioned, you can use PUT, maybe like this PUT /backups/456?resource=car&id=123, which says "replace the backup with id=456 with the one you will create from backing up the car with id=123".

Last, if you want to backup all your resources in one step, you could have a relevant parameter like POST /backups?all=true or similar. And if you want these backups to replace the previous ones, before running this, you can use DELETE /backups.

zafeiris.m
  • 4,339
  • 5
  • 28
  • 41