Search code examples
spring-bootrestrestful-url

REST API design for commands


I have multiple servers and I'm building an app to control them, check their status, etc. I want to create an endpoint that allows me to turn the server on/off, however, I'm not sure how to properly design the REST API.

Currently, let's say I have a Server resource and the endpoint to control it is /api/servers/{id}/start and /api/server/{id}/stop. They are used by simply sending an empty POST request which turns the server on and off.

This works fine, but I'm not sure whether it is a clean design of the API. I haven't been able to find any recommendations on this topic.

What approach would you recommend in this situation?

Thank you!


Solution

  • This works fine, but I'm not sure whether it is a clean design of the API. I haven't been able to find any recommendations on this topic.

    It is fine, but it could probably be better.

    Short version: instead of POSTing an empty message to a specialized resource, prefer to POST a detailed message to the resource you expect to change.

    Long version: any time you are trying to figure what to do in REST, the right starting point is to think about how you would do it with plain old web pages.

    On the web, you would open a page that has a list of different servers; each of those servers would probably have some sort of status indicator, and links for each of the changes you might want to make. Following that link would bring you to a form, which might be pre-populated with data. You would change any necessary defaults, and then submit the form, and the browser would create the HTTP request that tells the web server to restart server #7, or whatever. TADA.

    Notice that neither the browser, nor human being, need to know in advance which URI to use, because that information is included in the representation of the web page. The browser needs to know how links work, and how forms work. The human being needs to know which link to follow, and how to interpret the input controls in the form, but it is the server that decides what the identifiers are, and what key/value pairs should be used in the request body, and so on.

    Given that, how do you decide what the target of the form action should be? One possible answer is to consider the implications of caching. RFC 7234 says that a successful POST will invalidate any cached representations of the target-uri. So if you POST the request to the webpage that you expect to be changed by the request, then you get the appropriate caching behavior "for free".

    The cache invalidation rules are not flexible - they are designed to support the common case. If you have many cached pages that will be changed by a request, then you'll need to choose which one of them is most important for updating.


    Matching those ideas to your case: it's probably the case that the most important document changed by your forms is /api/servers/{id}, so that's the document that should be the target of your form submissions

    POST /api/servers/1
    Content-Type: text/plain
    
    STOP
    
    POST /api/servers/1
    Content-Type: text/plain
    
    START