Reputation: 379
I am designing a HTTP API for a system and plan to adopt a REST style. Part of this system's functionality is to manage Windows Services across servers. This naturally suggests endpoints like GET /servers/:id/services
to list known services on a server and GET /servers/:id/services/:name
to detail one. In addition to being created, deleted and updated (typical POST
, PUT
, PATCH
and DELETE
), services can be stopped, started and restarted. It's these operations that I'm not sure exactly how to handle. There strikes me as being three reasonable solutions.
Provide reified commands, i.e. POST /servers/:id/services/:name/start
, POST /servers/:id/services/:name/stop
and POST /servers/:id/services/:name/stop
, POST /servers/:id/services/:name/restart
.
Treat the operational status as a sub resource, i.e. POST /servers/:id/services/:name/operation
to start, DELETE /servers/:id/services/:name/operation
to stop and POST /servers/:id/services/:name/restart_required
to restart. (This last at least matches the internal behavior of the system - which does not immediately restart a service but posts to a db that the service is to be restarted.)
Make the operational status an attribute and use PATCH
to perform these operations, i.e. PATCH /servers/:id/services/:name/ {"status": "started"}
, PATCH /servers/:id/services/:name/ {"status": "stopped"}
and PATCH /servers/:id/services/:name {"status": "restart_pending"}
.
I'm not sure which is preferable. Option 1 is comprehensible, but it's not quite in the spirit of REST. Option 2 is conceptually a weird as it treats the attributes of a service as separate (if subordinate) entities. Option 3 is probably cleanest, the main difficulty is that it is not as obvious (would require reading the documentation for PATCH /servers/:id/services/:name
more closely. Any ideas of which approach (including any I've missed) most cleanly exposes this functionality?
Upvotes: 1
Views: 256
Reputation: 202346
You shouldn't use action within resources paths. It's not really RESTful. I think the last option is the best one according REST principles.
In fact, patch allows to do partially updates of the resource state. You're free to put what you want in the request payload:
For example simply the new value of fields with something like that:
PATCH /servers/:id/services/:name/
Content-Type: application/json
{"status": "starting"}
and the response could be if successful:
200 OK
{"status": "started"}
There is a specification for PATCH content called JSON Patch for more advanced usage. For example, if you want to add (or remove, ...) something in the resource state. You could have a look at this post in the section "Implementing bulk updates" for a sample of use: http://restlet.com/blog/2015/05/18/implementing-bulk-updates-within-restful-services/.
Another option would be to use the method POST
on the path /servers/:id/services/:name/
and provide in the content the operation to do. For example:
POST /servers/:id/services/:name/
Content-Type: application/json
{"command": "start"}
Hope it will help you, Thierry
Upvotes: 3