If people would simply advocate building applications which follow the semantics of HTTP instead of advocating "REST", many more people would understand the benefits and conform; there would be no need to write a thousand and one posts explaining what is REST. Unfortunately the original exposition of this way of building web applications was done in a dissertation, in a "scientific" style that I think Orwell captured so well (http://www.mtholyoke.edu/acad/intrel/orwell46.htm, worth a subscription of its own). Another problem is that unfortunately most web developers (not to mention "SEO experts") don't have any real understanding of HTTP or the principles behind the WWW, which makes them also unaware of the very practical problems certain design decisions can cause.
One thing I've always struggled with with REST, is how you should handle additional verbs.
As a contrived example, say we have a booking
GET /booking/:id
And we then want to cancel this booking, more specifically we want to trigger the "cancel" action (transition), which would change the state of the booking from "active" to "cancelled". There are a few possible ways to do this, and I'm not really sure which is "correct" for REST, or whether it actually matters:
POST /cancel (booking = /booking/:id)
PUT /booking/:id (state = cancelled, note this is dictating the resulting state, not the transition)
POST /booking/:id/cancel
CANCEL /booking/:id (custom verb, good/bad ?)
It would really depend on the semantics of the booking and the system. Another alternative would be
DELETE /booking/:id
Which is basically a more correct HTTP version of your last option. Otherwise, I would lean towards your second option (the PUT), as I would think that what you are doing is telling the server what you want the state of the booking to become. What happens server-side based on the PUT isn't really your concern as a client of the API.
> more specifically we want to trigger the "cancel" action
I'd posit that this is actually something that the API user shouldn't need to care about.
Good question though, I've often pondered it myself.
I think that a canceled booking is still a booking, just a cancelled one.
Here is wording from the HTTP spec "However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location. "
I don't expect the server to move the booking to an inaccessible location so I see this as a state change not a delete. Hence I am thinking PUT, not DELETE.
Exactly, it depends on the semantics. For example, if I'm exposing a salon's schedule as a resource, perhaps when a booking is cancelled it is thrown away (or otherwise made inaccessible). But in your case, you would still want make the cancelled booking available to REST clients, so PUT would be more suitable for you.
The resource you are changing is the booking resource identified by
/booking/:id
I would go with PUT /booking/:id with a status of canceled.
This makes sense to me because of the semantics of traditional FSM.
You are going from some state (active) to (cancelled). You are not dictating the resulting state, only that you would like to set the status to cancelled.
PUT can return an error in which case the transition failed.
It can return success and the transition is good.
This is exactly dictating the resulting state. Consider the FSM:
States = (active, cancelled);
Transitions = [("cancel", active -> cancelled)]
If the API says PUT status = cancelled, then we'd look through the transitions and find the one that matches our current state and the target state ("cancel"), then execute the associated code, the side effects of this transition - probably sending an email.
We now want to refactor the cancellation model to this:
States = (active, cancellation requested, cancelled)
Transitions = [("cancel", active -> cancellation requested),
("confirm", cancellation requested -> cancelled)]
You can see where I'm going with this already, the transition we want the user to take from the active state is the same, but the additional state means that we either have to change the API for cancellation, or have the PUT status do something other than specify the state we're moving to.
This is the reason I firmly believe changes of state should be requested by naming the transition, and why I'm not entirely sold on the "best" way to do this with a "proper" RESTful architecture.
I can see why this would be the case given the constrains imposed by the the REST architecture, but I don't really see what benefits this has over having some sort of "cancel" action to be performed on the booking resource.
Sidenote: Is it "better" to pass booking_id = number, or booking = booking resource URL. Why?
>I can see why this would be the case given the constrains imposed by the the REST architecture, but I don't really see what benefits this has over having some sort of "cancel" action to be performed on the booking resource.
The problem isn't so much REST, but HTTP: using a custom method could have the potential of creating havoc with proxies and such.
> Sidenote: Is it "better" to pass booking_id = number, or booking = booking resource URL. Why?
I think the ID should be the URL. It decouples the client from the internal IDs, which is not only DRYer (since otherwise you'd effectively have two IDs) as it can help if you need to change the internal ID format.
Because you are creating a 'cancellation object' belonging to that booking.
Ninja Edit: Really it is about being consistent, and predictable, so that people using your API can guess how it will act. If you are using an API of yours, and can't guess what the correct url/method is, you should change the API. (I forget who said that)
>Rather than letting clients construct URLs for additional actions, include the actual URLs with REST responses. For example, a "product list" request could return an ID per product, and the specification says that you should use http://www.acme.com/product/PRODUCT_ID to get additional details. That's bad design. Rather, the response should include the actual URL with each item: http://www.acme.com/product/001263, etc.
Yes, this means that the output is larger. But it also means that you can easily direct clients to new URLs as needed, without requiring a change in client code.
If you have your routes designated in a central area , this shouldn't be a problem anyways right? In fact, you need to designate this someplace anyways, whether it's on your server (in the database or in some code), or on the client-side code.
I might be missing something here though or just not quite understanding the problem.....
> If you have your routes designated in a central area , this shouldn't be a problem anyways right?
It's not a problem for the server (and even then, it might be: what if the root handler simply sends to further sub-handlers after just chopping off part of the URL or query arguments? There isn't necessarily a central URL authority on the servier either), but generally is one for the client: in a truly RESTful system, the client knows one URL and one only (the service's root).
It also knows all the media types the service can return (which is why meaningful content-types, as those returned by Github, are great).
From this, it can traverse the service to the place it needs, and it may cache URLs along the way (for more efficient traversals later on) but those URLs may die altogether and require a re-traversal.
This scenario is built into the architectural style.
> In fact, you need to designate this someplace anyways, whether it's on your server (in the database or in some code), or on the client-side code.
If URLs are designated anywhere in the client-side code (outside of the root service URL and a URL cache, which is accumulated knowledge rather than built-in), it's not a RESTful service, it's RPC-over-HTTP.
>If URLs are designated anywhere in the client-side code (outside of the root service URL and a URL cache, which is accumulated knowledge rather than built-in), it's not a RESTful service, it's RPC-over-HTTP.
But certainly the client needs to know something about the base resources such as product or user? How else will the client know where it can fetch the appropriate resource?
> But certainly the client needs to know something about the base resources such as product or user?
Of course, that's the "media types" part, it's the complete description/knowledge of a type of resource returned by the service. The media type returned by the service's root is the gateway to the rest of the service. That's the part which is generally missed in RPC-over-URL services claiming to be restful: they exhaustively describe the shape of all the URLs in the system, and then just quickly pass over the media types (the resources at these URLs).
That's doing it literally the wrong way around, a RESTful service documentation should be absolutely exhaustive in its description of the media types, the only "hardcoded" URL of interest to the client is the service root and it only takes a line to specify.
> But certainly the client needs to know something about the base resources
Yes, it needs to understand how they're represented, what types of links they might have to other resources, etc.
A good example is the Atom Publishing Protocol (RFC 5023). It's specified entirely in terms of representation formats, resource types, and the actions that can be performed upon those resources.
It will know by discovering URLs on each step — the same way you browse a website without knowing all of its URL structure in advance. Each HTML response has links and forms that show how to get the next thing.
Ahh, I think I understand where I'm misinterpreting things. I've been building a purely javascript based website so I've been thinking from that perspective instead of the more traditional page by page approach where this makes more sense when described in these terms.
It's definitely still possible to build a RESTful service, but I think if you're primarily building in js, you tend to have more routes that return resources without URLs to other resources than ones that do, especially when you're just starting out and don't have a comprehensive list of resources you want to represent and the accepted mime-types you'd like to be able to return.
1) REST is not suited to complex multi-variable queries or transactions
2) REST should be a stateless transaction
3) REST read results should be cacheable
4) REST can use headers to specify content-type/mime-type
REST is not a suitable replacement for all client-server interactions e.g. complex, sql-like queries over many variables. It is best suited to URL-like queries that produce singleton docs or lists of doc IDs.
REST in its most common form is a protocol over HTTP and thus can (and should) take advantage of HTTP's methods to provide CRUD:
Create = POST
Read = GET
Update = PUT (although POST is fine)
Delete = DELETE
> REST is not suited to complex multi-variable queries or transactions
Would it not be possible to represent a query or transaction as a resource, that you could GET/PUT like any other?
> REST should be a stateless transaction
I think there's a small grey area here around "stateless transaction". The HTTP request/response itself should be atomic (to be a bit loose with terminology), but the result can change the state of the system.
So the communication between client and server is the part of the system that is stateless. (Apologies if this was your intended meaning.)
One of the great advantages of REST is that makes data caching easy. Statelessness is a requirement for caching.
"Would it not be possible to represent a query or transaction as a resource"
Anything's possible just about but the whole point of REST is to create uniform resource locators for data. The problem with creating rather forced complicated URIs is that you quickly lose uniqueness: the same data will start being represented by more than one URI and therefore will start to be cached a multiple of times leading to conflicts.
It seems to me that if you want to learn REST, you'd be better off reading Roy's dissertation, which is pretty short and doesn't contain bullshit like, "Thus, REST uses HTTP for all four CRUD (Create/Read/Update/Delete) operations."
I'd recommend reading his blog instead, especially his analysis of services claiming RESTfullness. The thesis is not exactly clear, and I did not grasp the significance of what's now called "HATEOAS", the importance of media types and the lack of importance of URLs (as well as the complete irrelevance of "pretty" URLs to the restfullness of a service) until I read his blog posts on the subject.
REST != HTTP. HTTP, which is the language of the web is just an example of a REST implementation. A lot of people get this wrong. This should say Restful for everything, not REST.
Also to be REST compliant you have to employ discoverability and hypermedia.
There are two big ideas in REST. First one is in realm of system engineering, and second one in the realm of programming paradigms.
Using HTTP[S] protocol allows you to pass through almost every heterogeneous network. That means any highly restricted and protected (I prefer the term 'misconfigured') network of a cell phone provider, who blocks everything else, but http.
You can survive in that crazy hotel's or airport's wi-fi network, especially located in developing countries, which is a mess of cheap Chinese ADSL-modems and no-name Wi-Fi access-points with settings no one cares about.
It also means that you can pass through all these almost useless corporate firewalls made by idiots (why firewall if you have all those windows with IE6 boxes running by users with admin rights?).
The second big thing is about statelessness and using URI as a namespace - representing data as a file-system hierarchy and using one standard protocol everywhere - it is almost the same ideas which lays on the foundation of this enlightening Plan9 system. No xml, no BS, just names and simple standard protocol - 9P.
Together, those two ideas are enough to forget about all that proprietary crap, not because it is proprietary, but because REST is more general, flexible and easy to implement concept.
Can somebody explain in one sentence why is REST a good thing? What does it bring to the party? Why is forcing every RPC call that my application makes into CRUDdable objects necessarily a good thing?
Frankly, I can't believe the amount of near-religious attention it's being given. You're taking an obscure aspect of HTTP (already a mind-bendingly terrible protocol in its own right) - verbs - and making it the cornerstone of your application framework.
> [HTTP is] a mind-bendingly terrible protocol in its own right
Could you detail your thoughts on this? The more I work with HTTP, the more I get impressed with how usable it is. Granted, it's not suited for some domains...
Ok, I'm being somewhat unfair. HTTP is an adequate (although overly-complex) protocol for simple document retrieval. It is unfortunate, (in my opinion), that we've used it in a whole ton of ways for which it was never intended.
Have you considered some of the hacks that we have to use to make HTTP do what we want? Comet/longpoll? JSONP? Have you looked at the bajillion different ways in which browsers and proxies fail to implement caching in a consistent manner? How browsers will only allow a limited number of concurrent connections to a particular host? Have you looked at a x-www-form-urlencoded post? Do you think that's a good way to send data around?
Anyway, I'm not really after a big discussion of HTTP's merits - my apologies for excessive opinionation. I am, however, interested in why so many people think REST is a magic bullet.
> Have you considered some of the hacks that we have to use to make HTTP do what we want?
Right, but this sounds like blaming a nail for permanently attaching something when velcro would have been more suitable. Granted, we haven't had many other options, but to me the surprising thing is that HTTP is flexible enough that all of these hacks can be done.
> I am, however, interested in why so many people think REST is a magic bullet.
Well, more accurately, I'm blaming people who think that nails are awesome and the only way to do things - and in fact we should structure all our applications by making use of a relatively obscure aspect of how nails work :)
REST facilitates loose coupling between clients and servers, scalability, caching, retrys etc. REST is a good thing because it provides the right abstractions for some applications.
A slow, unreliable interaction with a remote server is different than an interaction with an in process function call.
If ignoring this complexity is causing no problems then concentrate on what does cause you problems, then just learn enough about REST to recognize a problem in the future.
SOAP v1.0 tunneled everything over POST so you could not cache responses.
A frequent non-restful solution is to return a domain specific id to a client and have the client 'know' that the correct URL is say http://{base}/product/{id}.
The restful solution is to return the URL to the client have them use it what is given rather than construct it. The restful solution allows for many product servers which are independent from the original server. This makes for looser coupling and improved scaling.
REST is essentially what they were thinking, or now think they should have been thinking, when they designed HTTP. So truly honoring the spirit of HTTP gets you close to REST.
But we've known to use GET for operations with no side-effects, and POST for operations that change stuff for many years now, without needing to attach a name to it, throw PUT/DELETE into the mix, or CRUDdifying every operation.
It's the verb part that I really don't get. That, and the general level of excitement surrounding REST. Why are there so damn many articles like this one?
The advantage of the PUT/DELETE verbs is that they are idempotent. If they fail an intermediary or you can safely just apply them again on the same or a different server.
The author of this article has a different understanding of REST than I do. For instance I strongly disagree with this: "One option is not acceptable as a REST response format, except in very specific cases: HTML, or any other format which is meant for human consumption and is not easily processed by clients." I think well marked up HTML is potentially the best response format as long as it is easily understood by clients. And I think this has nothing much to do with REST. Naturally I become motivated to write my own article about REST spelling out how my understanding is is different. Thus the number of articles on REST multiples as a chain reaction until 99.99% of the articles on the internet are about REST. But my 1 year gave me a bad sleep last night dampening the my motivation and saving the world.
In many ways, the World Wide Web itself, based on HTTP, can be viewed as a REST-based architecture.
In every way, the WWW is a REST-based architecture. REST is an analysis of the web, as it existed at the time. There is no more perfect exemplar of REST.
This is a crucial point. Fielding's paper is about how and why the web works. It's not, per se, about how the web should be used to make network services, though many have tried to derive that from it.
The real focus for web services needs to return to SOAP. SOAP is a truly contractual design that solvs many of the problems that have to be solved by hand in REST, do we use JSON or what to transfer the data? How about argument types? REST is like a nice way to express HTTP other than that SOAP was designed to and solves web service problems very well.
(I find it very distasteful to downvote parent's comment without replying. It's a valid opinion, not a troll)
You're right that REST doesn't provide everything SOAP does, because SOAP is a specific protocol and REST is just an architectural style. On the other hand, there are already specific protocols to achieve that in a REST style (and reusing HTTP), like WADL.
Furthermore, it's not clear that a one-size-fits-all approach like SOAP takes is the right way. XML is great for some use cases but not others; by pigeonholing everything to it you create inefficient systems filled with hacks to avoid its shortcomings in certain domains.
SOAP in particular seems very strict, while REST based systems - particularly the Web - are designed to make an heterogeneous mix of decoupled services and clients work well together. The idea that a client should break if the schema changes, for example, leads to very brittle systems.
>> The idea that a client should break if the schema changes, for example, leads to very brittle systems.
Thanks for that, much appreciated.
>> The idea that a client should break if the schema changes, for example, leads to very brittle systems.
That's the point, imagine building the web using string values instead of constants. With constants, if it changes, you immediately get notification from the IDE via the compiler and can fix it straight away. If it's a string, then it's up to the poor testers to find it and good luck, it has to be in a known use case.
I think for general communications REST is better than not following any standard by far. For web services though, my money is still on SOAP and I'm a Java/Linux lover not .NET these days, SOAP is still best for Web Services in my view.
An article describing rest should link to rfc2616 which actually has quite a bit to say about using HTTP and REST (without ever using that term). http://tools.ietf.org/html/rfc2616
What happens when you need to request some data and therefore use the GET method, but also are passing sensitive data in the query? Should you use POST in this case in order that the sensitive request is not logged?