REST API Design – RESTFulness of /action Endpoints

apiapi-designrest

I have been looking at examples of good REST APIs, and I read that Rackspace's cloud servers API is often cited in comparison with AWS's RPC-like EC2 API.

However, I also saw that their API reboots a server like so:

POST /servers/{server_id}/action

{
    "reboot" :
    {
        "type" : "HARD"
    }
}

While this makes sense for the particular scenario, it's less like the posting of a new resource and more like invoking a method on an object.

server = Server(id)
server.reboot("HARD")

I have seen similar things elsewhere – for example, the Restful Objects spec. There, GET /servers/{server_id}/actions/reboot might give a description of the action and its parameters, and a POST /servers/{server_id}/actions/reboot/invoke would actually call the action.

Does this way of doing things (resources with "methods" as well as data, sort of like OOP in API form) count as RESTful? And, even if not, are any of the purported advantages of REST lost in APIs which follow this sort of design?

Best Answer

While this makes sense for the particular scenario, it's less like the posting of a new resource and more like invoking a method on an object.

RFC 7231 4.3.3

The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.

In short, in the uniform interface of HTTP resources, POST is the catch-all; you use POST if none of the other methods are more suitable

(Always be keeping in mind that the web has been spectacularly successful even though the HTML media type only offers GET and POST).

Does this way of doing things (resources with "methods" as well as data, sort of like OOP in API form) count as RESTful?

How does the client know to send that message-body to that endpoint using that method? One of the key ideas in REST is that the communication of that knowledge happens in band; the client knows to send that message to that endpoint because the representation of application state that was just provided by the server told it to.

In a word: hypermedia.

In other words, think about how you would do this on the web: you would load up some bookmark, which would return you a representation with a bunch of semantically annotated links. You'd follow the shutdown server link, which might return you a representation with a form so that you can choose which server you want. That gets you a representation of the available actions; which includes a link to follow for the reboot action. You follow that link, and it brings you to a form where you can specify the type of the reboot. You submit that form, and the the message for rebooting the system is processed.

The key ideas here are that you never needed to know any of the URI, except for the initial bookmark, and you never needed to know what method of the uniform interface to use, except for the bookmark. All of the rest of the plumbing comes from the representations provided by the server.

Your client (the browser) needed to know the media-type of the representations; to find the data describing the links and methods, and to find the semantic data to provide to you. You yourself needed familiarity with the semantics (what does reboot mean?), so that you could follow the protocol, but you didn't need to know anything about the plumbing.

Fielding, writing in 2008

I should also note that the above is not yet fully RESTful, at least how I use the term. All I have done is described the service interfaces, which is no more than any RPC. In order to make it RESTful, I would need to add hypertext to introduce and define the service, describe how to perform the mapping using forms and/or link templates, and provide code to combine the visualizations in useful ways. I could even go further and define these relationships as a standard, much like Atom has standardized a normal set of HTTP relationships with expected semantics....

In other words, it's not just about the endpoint, but also the journey to find it.

Does this way of doing things (resources with "methods" as well as data, sort of like OOP in API form) count as RESTful?

So using the specific example of this API, I would argue that no, it doesn't count as RESTful. The fact that the response is application/json, a media type that does not define a standard for links, is a big warning sign. Furthermore, it appears that all of the information about the message-body to send to the host is described out of band, rather than within the exchanged representations.

And, even if not, are any of the purported advantages of REST lost in APIs which follow this sort of design?

The primary thing that's lost is the ability to change the resource identifiers and methods used by the uniform interface. For instance, in HTML we can switch a form from GET to POST (or vice versa) simply by making the appropriate change in the representation; we can trivially switch to a different URI namespace because the client is just following the link as represented in the hypermedia.

For example, the Wayback Machine works; a spider can crawl the safe endpoints in your API (and know which ones are safe to crawl just by looking at the representations of the links), gather up the data, replace all of the resource identifiers and make the results available. The client can follow the links in the wayback machine just as easily as it can those in the original API, once provided with the correct starting point.

one could very easily change it to POST /servers/{server_id}/actions/reboot/invocations,although it feels like a bit of a cheat.

REST doesn't care what spelling you use for your identifiers. They are opaque; any meaning encoded into them is done so at the discretion of the server and for its own exclusive use.

As far as REST is concerned, the following request line is entirely consistent with a resource that reboots a server

POST /5dc2a243-f00b-40df-84b2-dbed81d73331 HTTP/1.1

if this sort of pattern was repeated throughout the API, then this would make it RESTful

Yes

even if there are endpoints which look like they are describing verbs or processes or actions rather than nouns/things/resources

Yes.

URI design is a completely different concern from REST.