views:

201

answers:

6

Along with half of the web developer community, I've been struggling to really and truly grok the REST style. More specifically, I've been trying to form some opinions on how practical a pure RESTful architecture really is between a web browser and an application server.

As part of my learning endeavor, I've been taking a look at some online examples of REST, specifically Twitter in this case. In their API documentation, they discuss their various "REST API Methods".

I'm struggling with rationalizing how exactly most of these are actually RESTful, beyond having a RESTful URL structure. Consider, for example, a simple GET request to http://twitter.com/favorites.

In a pure implementation of REST, I would expect identical requests to that URL, regardless of the initiating client, to return identical responses. In this particular case, though, we would obviously all see different responses depending on our currently authenticated users, which implies that our requests are being connected to some form of client state on the server before a response can be generated.

Hopefully that provides enough context for my question then - can that really be called "REST"? I get the impression that 90% of the so-called RESTful implementations between web browsers and application servers demonstrate this same inconsistency, where the restrictions on client state stored on the server are ignored.

First question on SO, btw... been a fan of the site and community for a long time though!

P.S. This isn't in any way a slam against Twitter... it's just a real world example for my question.

*edited to remove my conflation of statefulness and idempotence in the original question.

+2  A: 

In this context, idempotence is a tricky word. Even if you were retrieving an individual tweet, you would get a different result if that tweet were editable and someone edited it. When retrieving a list, I would certainly expect a tweet to retrieve the most current list.

It might be more helpful to think of idempotence as the ability to do something without causing side effects. So a GET is idempotent in this sense, but a POST is not.

From Wikipedia:

In computer science, the term idempotent is used to describe methods or subroutine calls that can safely be called multiple times, as invoking the procedure a single time or multiple times has the same result; i.e., after any number of method calls all variables have the same value as they did after the first call. Any method or subroutine that has no side effects is also idempotent.

Also from Wikipedia:

Methods PUT and DELETE are defined to be idempotent, meaning that multiple identical requests should have the same effect as a single request.

In contrast, the POST method is not necessarily idempotent, since sending an identical POST request multiple times may further affect state or cause further side effects (such as financial transactions [e.g. a customer getting mistakenly charged twice for the same product]).

See also:

How I Explained REST to My Wife
http://tomayko.com/writings/rest-to-my-wife

Robert Harvey
PUT is idempotent. But it is not safe. Get is idempotent and safe. Your definition of idempotency is actually the definition of safe.
Darrel Miller
That's a good point... perhaps idempotence was the wrong thing for me to harp on then. I think statelessness is really more at the heart of the question. At first glance, it feels like it's clearly _not_ RESTful (due to state issues)... but services like this are so widely recognized as RESTful, I wanted to be sure I'm not overlooking some rational for that...
jmar777
@Darrell: I clarified my answer a bit, replacing PUT with POST, and added additional supporting material.
Robert Harvey
Actually, services like this are widely labeled as RESTful, however, they are certainly not recognized as such by people familiar with the REST constraints.
Darrel Miller
I'm not sure server state is a sin that twitter is actually guilty of. My experience with the API is that you can (at least you could) just use basic auth to access any endpoint. There is no need to login and initiate a session before making requests.
Darrel Miller
@Darrell: with the given example, who's favorites would you expect to see then, outside the context of a user's session?
jmar777
@Robert How does your answer address the question? What part of the Twitter api violates the HTTP specs definitions of when methods should be safe and or idempotent.
Darrel Miller
@jmar777 There is no session. The request is self-descriptive. The only mistake is that the server needs to use the authentication info to identify the user in order to return the correct favorites. Interestingly, the twitter api also supports a proper URI format. e.g. http://api.twitter.com/1/favorites/bob.rss Using this format the resource is uniquely identified by the URL.
Darrel Miller
@Darrel: Hm, perhaps I was answering the original question, and not the edited one. To be honest, philosophical arguments about terminology don't excite me all that much.
Robert Harvey
@Darrell: Right... that example looks legitimate to me, but I still don't see how the <http://twitter.com/favorites> example is "kosher". The URL by itself doesn't contain enough information to fulfill the request, and I don't see my username in the cookies anywhere... so I can only assume that the server is having to reconnect to some client state (via my session cookie) before it can know how to fulfill the request.@Robert: Ya, my bad. I removed references to idempotence since I was conflating the term, and it wasn't conveying what I really meant to ask...
jmar777
@jmar777 The user identification is in the Authentication header. At least that's how it used to work. Not sure how OAuth works.
Darrel Miller
A: 

Technically, no, it's not RESTful. It's not stateless (a.k.a. idempotent as you mentioned) for one thing.

Josh
+1  A: 

As the REST FAQ explains, the term "REST" is used to cover a wide array of things, including stateful applications that are structured in a RESTful style. Because the state is mostly being passed by the user in a cookie rather than stored on the server, it's considered RESTful. Roy Fielding (who invented REST) commented that as long as the entire state is being passed by the user, rather than a reference to state on the server, it's RESTful, since the same GET request will return the same result. Twitter's REST API is close to doing this, but not 100% there. It's not strictly the original meaning of "REST," but the interface and general philosophy are similar enough that it generally gets pulled under the same umbrella.

Chuck
+6  A: 

Twitter breaks pretty much every REST constraint. Your example of http://twitter.com/favorites returning different results based on the authenticated user is an example of Twitter violating the "Resource Identification" constraint. Each interesting resource should have a unique identifier. My Twitter favorites and your Twitter favorites are two different resources and therefore should have two different URIs.

This actually is not related to idempotency at all. Idempotency is about being able to make the same request multiple times and it have the same effect. Even Twitter respects idempotency. If I GET my favorites multiple times, I still get my favorites back. How many times I do GET does not affect the result.

There are many other ways in which Twitter break the REST constraints. Many of these issues have been covered here on SO before.

Update After perusing the Twitter api docs a bit more there is actually an alternative URI format that does properly identify the favourites resource. Here they show how to create an URL like:

http://api.twitter.com/1/favorites/bob.json

It still is a long way from being RESTful, but at least that's a step in the right direction.

Darrel Miller
Thanks - that makes a lot of sense. I edited my original question to remove the confusion over idempotence and statefulness, btw...
jmar777
Darrel, I wouldn't say that returning different results based on authenticated user is a violation of the Resource Identification constraint: The URI merely identifies a resource described as *The currently authenticated user's faves*, just like `http://twitter.com/home` is my twitter page, and `https://www.google.com/history/` is *my* history and not yours. It's not as useful to link to, since it inherently means something different to everyone.
mogsie
@mogsie I'll dig some more. I'll let you know if I find something more authoritative that supports either yours or my perspective.
Darrel Miller
A: 

Looking at the documentation, the usage of the word "method" is probably a good indication whether that API is truly RESTful or not. There are a couple of resources that might actually qualify as such, like friends/<user-id> or favourites/<user-id>, but most of the resources are really just procedures, like account/update_profile_image for example.

The way I see it, in REST an URI should really just specifiy a thing, and not what you are going to do with it. If there is a verb in the URI (like update), you are most likely doing it wrong.

Tim
A: 

Reading the twitter api i've come under the understandment that the restful api will be obsolete in a couple of weeks. Instead you should use the oauth authetication method.

vlad b.