The biggest problem with today's REST implementations is that they're essentially a database serialization layer. Consider how a RESTful Rails model is typically represented as:
How do you get more info on the author if you only have this piece of information? Rails/ActiveResource guesses through convention: "/authors/2", but that might not be the case, which makes this approach very brittle.
The REST client would then be able to traverse the representation without making guesses at the URL, and if the end-point of '/authors:id' changes for whatever reason, the href would be updated accordingly.
Pagination/large data-sets could be solved as well:
... and a bajillion other common RESTful API problems through better convention.
I'd agree with the author that REST is misunderstood, but my opinion is that its misunderstood on the grounds that today's "REST" implementations are lame database serializations. The web has been doing this since the <a href/> tag was conceived, but for some reason, modern REST implementations left this out.
The biggest problem? I'd say the biggest problem is browsers not fully implementing HTTP's REST support. Instead of having a different API for every freakin' website on the planet, we could use HTTP and actually implement GET, PUT, POST, DELETE.
It's sad that it didn't happen in XHTML2, and also removed from HTML5.
Upvoted because I like your solution for pagination and for further information via an :href attribute. However, I don't see a real problem with the way Rails does things because it's "by default" and I think a dev ends up causing a lot of unnecessary trouble for himself by using stock to_json. The more I work with Rails building out a JSON API, the more I realize that .to_json is just another way to "scaffold" - it's not useful in production. :)
I can see that point ... but where's the direction on what to do next? What's the post-scaffold JSON mechanism? Bonus points if it lets me generate/embed urls with the knowledge/techniques I have from making web pages.
If you say "erb", please don't be offended by me laughing.
It's also worth noting that to_json should not be invoked directly these days in favor of as_json. It's now meant to more or less be an internal Rails API.
The RESTful way to solve such problems is not just by better conventions, but by conventions standardized by the appropriate media types. E.g., the REST service may define a
that means that all "href" properties are URIs that may be paged by appending "?page=NNN" to them. If both server and the client understand this content-type, the representation may omit the "rel:" part from the parent example altogether.
Constructing arbitrary URIs by the client is not RESTful; however in this case it's the server-side that is in control of URI generation mechanism (it could serve a different representation, with a different Content-Type:, if it chooses to) -- thus it's perfectly valid from the REST point of view.
This is the same story as with the HTML <form> element. It also allows client to construct URIs by the specific rules known to both sides -- because the rules are defined by the appropriate standards about text/html.
I disagree that "REST is just kinda that [database serialization]"; it is one approach to REST, but its brittle and tends to bias developers towards over-engineering their API into these tiny little pieces that correspond with each database table or model.
I'm designing the API for Poll Everywhere right now. Internally a multiple choice poll resource consists of several database tables and Rails models, but I simplified the externally facing JSON representation down to:
I've ended up doing without ActiveRecord's to_xml/to_json to (among other things) accomplish HATEOAS within Rails. Instead I'm using xml builder and a roughly equivalent json-from-ruby-hashes template system. The process is a bit ugly at times, but so far the results have been pretty promising. We've already had api changes break enough internal clients that people are pretty excited about that never being their problem again.
I could wish that Rails had a cleaner path and this regard, though. I've never understood the thought process behind Rails' serialization system. Why use MVC to deal with html and email but almost ditch it entirely for other document formats? Especially when we're dealing with something that could really benefit from embedded hyperlinks.
I realize I implied "every table or model", and I would always argue for composition the way you describe it.
But ... there are good reasons to decompose and expose these things in your API. While maybe not for Public consumption but certainly for Private.
It's my opinion that the way REST beats SOAP in the enterprise is that in almost all cases it's much quicker to build decomposed services. And then likewise composition of said services is also much easier.
You would just have to include the URL where the client should POST the vote to (like with <form src=... in HTML pages) and it would be perfectly RESTful, imho.
Of course, it would be better if there was a Standard Poll Format to avoid the proliferation of custom formats that reduce code reuse, but alas, I don't think there is.
If you need page stability you can refer to the items at the top of the page not the page numbers, the nice thing about rest is they are still just next and prev links.
I thought I finally had REST figured out until I read this.
Does anyone else see a diminishing return on pedantically following the REST-prescribed design and actually creating an API that people are familiar with out of the gate? I feel like if I followed this article to the T in my current design, anyone trying to integrate with it would spend so much time reading my API documentation just to figure out why they weren't getting an XML reply that it would stop being productive.
I am working on an API for imgscalr right now and I think I have it about 80% RESTful at the moment -- the parts I'm not doing is paying any attention to the headers either coming or going between client or server.
I'm using the more recent "classic" /path/object.{format}?arguments format that I have seen folks like Wordnik and Vimeo use.
It may not be purely RESTful, but it is intuitive and I can't help but think: "Remember 3-4 years ago when REST wasn't all the craze and no one knew what it was? The web still managed to function back then..."
I'm trying to mix some practicality in a bowl filled with "best practices" and come up with something that most people can stomach.
I hope I hit that mark, but we'll see. As far as I'm concerned I'm sticking with the versioned URLs because I find it more intuitive for endpoints that change, get renamed or are removed than slamming one inside of a mime type or header or even a query string param a la AWS.
using object.format is perfectly ok regarding the rest. using headers might be more pure, but its not the biggest issue.
the biggest issue with the rest-wanna-be interfaces is their use of object ids instead of object uris. so that I have to construct my own urls to access stuff.
in a proper restful api you are NEVER supposed to construct your own url. you are supposed to get all the relevant ones from the service.
and this kind of api is actually much more user friendly and allows for much better discovery. you just get the single top api url which has references for all the available collections objects and operations right there in the result.
where the arguments specific to the noun (or object/entity or image resource in this specific case) go in the query string, but the URL stem itself must be a valid resource reference?
Part of the problem is that the fundamental idea behind REST has more depth to it than most developers care to understand, so the parts that most designers, developers and consumers of "REST" APIs think they are in love with is a rather superficial part of it.
This makes things really confusing when people talk about REST because you can't really know what they mean by it.
He's right, but older web developers might remember the alternative, which was having no design pattern at all.
Most web developers aren't going to read the computer science papers about REST, and how strictly you want to adhere to it, depends on you, and your development team. It's a design pattern, or a tool, but it's not a religion.
On that note, I've gone into several job interviews where they ask me to explain what REST is, and I always start with, "REST stands for Representational State Transfer...", at which point, I get the feeling that the interviewer wasn't aware of that, and I wind up telling them way more about REST than I think they wanted to know.
I read the post and I have to say that he's got a nice flamebait title but totally avoided the thorny issues that people argue about. In fact, I'd like to be pointed to a solution for the following problems:
1. I'm an old Web programmer, and my introduction to the Web started with HTML, not HTTP. I don't just write APIs, I write Web apps. I find it difficult to explain to people what this means:
<form action="/some/noun" method="POST">
If you are religiously RESTful, you probably think this is fine. But I'm a religious English reader. When I see the word "action", I think of a verb, not a noun. When I see the word "method", I think of "how", not "what". So when I look at the HTTP spec, all the HTTP "verb"s look to me like how-I-should-do-something, instead of what-to-do, and the resources (URLs) look to me like the what-to-do, instead of what-they-represent.
Small semantics issues I suppose, but here's another one:
2. HTTP is not a programming language, and yet it demands a (very) finite set of actions and an infinite set of objects to model the real world, where there are an infinite number of actions and objects. What I mean is, in Java or whatever OOP language, I can define classes to model objects and define methods in classes to model actions on objects, but I'm not sure if I can do it pragmatically in HTTP without getting yelled at.
3. HTTP statuses. Almost the same problem as the above. I have many different kinds of statuses, not all of them fit in the finite set of HTTP statuses, and they don't always provide the granularity I want. Can I return a non-standard status number? How would the clients behave? I have no idea.
4. Being RESTful means not being stateful. But you see, there's this thing called session and login cookies and many other tracking cookies that I have to take care of. Again, I don't just write APIs, I write Web apps. I would like to not do multiple handshake requests just because a paper says I should. I would also like to not get yelled at when I decide not to.
5. HTTP is RESTful, thus HTTP is REST. Please don't tell me HTTP is the best we can do. Can I have something more minimalist, extensible and powerful enough to model the real world?
- REST is an architectural model for building web services.
They are all different.
> HTTP is not a programming language..
> HTTP statuses
> REST is stateless
HTTP is a protocol. A protocol by definition allows certain constructs and prohibits others. There are books available for modeling real-world problems with REST, such as RESTful web services cookbook. I'd suggest going through them, before declaring REST is impractical.
>I'm not sure if I can do it pragmatically in HTTP without getting yelled at
You can certainly use HTTP as you like it, just please don't call it RESTful unless it actually is. A lot of web APIs are not RESTful, nothing wrong with that.
> don't tell me HTTP is the best we can do..
Unfortunately it is for now. Everybody is free to invent their own protocol, write production quality servers to implement it, and get everybody else to adopt it.
1) HTML isn't English, it just has some similar sounding tokens. You can't assume the semantics are the same.
2) Well, there's HTTP and there's REST, they're related but no the same. HTTP is a full protocol, completely defined; you can't add more verbs, period.
REST is an architectural style. It has a series of constraints, and it tells you that if your system architecture complies to them, it'll have some useful properties, like low coupling and such.
HTTP is just an example of a RESTful architecture.
Now, if you're designing an architecture and you want to follow REST, you can choose the verbs you want, but these should be generalist and not tied to specific names.
This provides an Uniform Interface, which simplifies and decouples the the architecture.
3) See above. HTTP statuses are fixed, you can't return other stuff. If you're designing your own architecture, you can use whatever you want. Hell, you can return different pictures of kitties for each status if you want to.
4) As the Zen of Python states, practicality beats purity. But you should be aware that by adding state to the connection, you'll lose some advantages.
Let's say the user is performing a multiple step action, and the server he's using breaks.
If the server was holding the state, now the user has lost all the work and he'll be pissed at you. If on the other hand, the state was saved by either the client, or more "RESTfully", by the mere fact that he was on a specific URL, than any other server can pick up where the other left without annoying the user.
5) Sure. We just need to rewrite all the browsers and servers worldwide, including a bunch of embedded ones that can't be reflashed. It's possible...
The original stateless way has fault and partition tolerance baked right in. By breaking this convention you open yourself to a world of hurt, no matter how many band aid concepts you patch over it.
If you had ever designed or worked on a distributed system that needed to scale you wouldn't talk about adding servers and sharing state (distributed anything).
Sure distributing state is a fail-safe strategy - but not a scalable or performant one.
It's actually kind of lame that this pompous flamebait makes it to the top of HN, and then he concludes his post saying he doesn't take comments on his blog. excusez-moi, what is he the New Yorker? I'd prefer to address his pomposity on his own turf rather than here, so all I'm going to say is this has all been said before, and it's a bitter irony to spend time talking about flogging dead horses while debating the semantics of a meaningless buzzword with nobody but yourself.
Very good read, and thorough. I particularly like the transaction example. It seems like a common idiom that trips people up with REST.
However, I do have a problem with REST that I've been dealing with lately. Specifically, the question of web-hooks. Many services today allow you to pass a URL that they will hit with a POST request whenever something happens. A good example is the GitHub post-receive hook (http://help.github.com/post-receive-hooks/). So, to be a good student of REST, I create an /update resource for the POST (similar to the /transaction example from the article). However, /updates might come in a variety of formats. Not just JSON vs XML, but GitHub vs Gitorious vs Beanstalk vs etc.
So, how do I handle these "formats". Presumably the "Accept" header is out of the question (unless the provider happened to know about MIME's vendor extensions and used them). So then is it acceptable to add a parameter? Use "/update?from=GitHub" for example? Or, is it appropriate to use an extra path element like "/update/GitHub", since the resource really is a "GitHub update", not just a vanilla "update"?
There's no right answer, but it's helpful to think about it from a data modeling point of view.
If where the update comes from would be stored as an attribute (i.e. column in the table), use the parameter option (/update?from=GitHub). If, however, they'd be separate types of updates (i.e. separate tables), use the separate URIs (/update/github or /github_update).
This is an analogy, of course, as there's no need for a 1-to-1 resource-persistance mapping, but it's a useful way of thinking about it, I think.
I don't see what's the problem. Github is the client, so they POST to you the data, so they should include a 'Content-Type' header with the format of such data. Then you can process it accordingly.
What I've seen in the past (mainly from Pylons) is to have an extension on the end of the URL so: /updates/ has a default format say XML and then there's a JSON resource called /updates.json, /updates.txt, etc.
Keep in mind what the R in REST stands for. Each resource is a representation of internal data. You can have multiple representations under different URLs even though they're powered by the same internal data structure. Ideally you'd use the Accept header to do it but sometimes you need to be practical.
"Each resource is a representation of internal data. You can have multiple representations under different URLs even though they're powered by the same internal data structure."
False. Each resource is a resource. The representation and the resource are completely independent.
I disagree. A resource is a concept, not a representation of it. A resource in a car dealership is a 'car', not an ' XML document about a car'. One of the examples given by Fielding are "today's weather in LA"; that's not the representation, it's the actual concept.
The concept of internal data structure doesn't enter the picture at all; for all the client knows, the response might even be generated by a monkey typing on a keyboard.
So if you're using different URLs, you're saying that those are different resources, not multiple representations of the same resource.
Sure, it may be useful and 'practicality beats purity', but it's bending the concept.
My case boiled down to, “A URL represents the path to a resource. You should be able to remove any number of parts from the end of a URL and be left with a different, meaningful URL. In the case of search, the terms are options that describe what you want returned by the search, not resources.”
His case boiled down to, “A URL is a sentence. You should be able to read a URL as English and get a good idea of what it represents. In the case of search, adding more path components adds words to the sentence to make the search more specific.”
He pointed out (paraphrasing) that URLs are a language — and languages evolve. URLs as paths better embodies the RFC, but a new style of URL might be more meaningful on today’s (and tomorrow’s) web.
Slash-divided parts of URLs generally seem to me to describe a hierarchy, both because of the traditional structure of many URLs and slashes' traditional usage as a hierarchical path-delimiter. So I personally prefer your proposal because it makes a to-me clearer distinction between the resource that's being specified and the rendering attributes applied to the presentation of that resource. So it seems more obvious at a glance which parts of your URL could be removed/changed and what would happen and it just "feels" more right.
I'd say your friend has bad taste and shouldn't be allowed to design the URL structure of your site. Your style is better, but neither is more or less RESTful because REST doesn't say anything about pretty URL. URL's don't have to be hackable to be RESTful, but it's nice. URL's don't have to be pretty to be RESTful, but it's nice. You have better taste than your friend. Your search however, is more RESTful than his as all of your searches use the same URL. You understand what a resource is, he doesn't.
An URL is just a name. /network/girl_talk is just as valid as /uwef9. HATEOAS means that clients shouldn't know a-priori of any URL except for the entry point.
In the search case, I think your coworker is wrong, since that would mean you have to construct URLs by 'hand', which violates HATEOAS. GET or POST parameters should be used to avoid that.
That doesn't look like a hierarchical resource. You probably don't list sort options under /search/bass/sort/, and even then /search/bass/sort/artist/ wouldn't be logical subset of that.
This URL looks more like a different view on /search/bass resource, so /search/bass?sort=artist is IMHO more appropriate.
The standard is to use / for hierarchal data and URL params to alter the resource's content. For instance:
/search/ would be an empty search, and for the sake of argument let us say that it returns the entire collection.
/search/?query=bass
This would restrict the collection to return only records that contain the word "bass". Based on the way that URLs are defined, these are considered separate resources.
The same with this URL:
/search/?query=bass&page=10
This is a different resource than the previous. In this case, sometimes it feels like the page should be a member of the search collection. It's up to you whether you prefer a URL like this
/search/pages/10?query=bass
In my head that is incorrect because to me the query string manipulates the last item in the hierarchy which is "pages/10". So the order of operations would look like this:
1. Select the first page from the search collection
2. return only items on the first page that contain the word "bass"
Either way I don't think it matters. Just get it done. Clients do not care about URL structure, they just want their problem solved. I redid an app and prettified the urls (yes I know this is slightly off topic) and no one has commented on it.
Developers will use either, just do it and provide documentation and be done with it
Exactly. REST is interesting, but understand why its interesting. If you're doing it because its a popular buzzword, that's just cargo cult.
It's good to know about REST so you can use it where it makes sense. But at the end of the day, doing what is right for your app trumps following any given methodology.
But then it's important to document when you're breaking the constraints. Nowadays it's impossible to know if a web service is actually following REST or not because everything remotely similar gets the same label.
> Either way I don't think it matters. Just get it done. Clients do not care about URL structure, they just want their problem solved. I redid an app and prettified the urls (yes I know this is slightly off topic) and no one has commented on it.
REST doesn't really care about pretty URIs either, in fact one truism about REST is that people who spend a lot of time worrying about pretty URIs are probably missing the more important aspects of REST.
Oh and I agree with you, people can spend a long time coming up with pretty and hackable URIs and in my experience clients often just don't care (sometimes its worth the effort though).
i) most successful "RESTful" APIs don't really follow all the REST principles (e.g Flickr, Amazon, Dropbox). My thumb rule is this: If an API does not start from a "mother" URI that gives you the most updated list of resources that can then be requested by the application, it is not really HATEOAS.
ii) a purely resource-oriented view of your entire API space shoehorns you into doing really strange things to keep REST "purity"
So my conclusion is that using an architecture/concept originally intended for humans navigating hypermedia documents may not be a natural fit for parts of your API that cannot be modeled as such. See the Dropbox REST API documentation (http://www.dropbox.com/developers/docs#api-specification) (" Section: Deviations From Standard REST Style") to see an example of the pragmatic decisions taken.
The web has grown organically and it has the warts to prove it. It's useful to think about the spec and to work toward improvements, but if it's real world possible to have your services work well for mobile clients on m.domain.com and real world impractical to do so on your main domain (or any of the other examples regarding actions, languages, versioning, whatever)—then by all means, break the rules.
I think his main problem with the m.domain.com was redirecting to the main page. If it did a 303 See Other to the mobile version of the same article it wouldn't break the spec, as far as I can understand it.
I don't know if any browser will implement this or has implemented it, but in real world scenarios we'll probably have to stick with .csv and en/foo or ?locale=en for a couple of years...
> Is there any way to make the browser do an Accept: application/csv header on a hyperlink?
Sadly no. Browsers suck ungodly amounts of dicks in their handling (or absence thereof) of the Accept header. I don't know of any web browser with an even remotely useful behavior on that one.
Accept header is all but useless these days. Servers rarely look at the Accept header that is sent with the request, and browsers can rarely know ahead of time what type of content to expect when merely clicking on a URL. Check out this blog post by Eric Law on IE and the Accept Header (http://blogs.msdn.com/b/ieinternals/archive/2009/07/01/ie-an...)
If you do use content type negotation, you are best off giving each type a different url (with the conneg doing a redirect) if the representations are usefully different ie you might want to bookmark one or the other.
In practise no one does use it, so just forget about it.
good point, as long as the browsers don't have convenient way of displaying you the possible displayable mime-types this function isn't very useful to the enduser.
Some of this feels like trying too hard to adhere to HTTP. For example,
> Accept: application/vnd.steveklabnik-v2+json
This declaration loses information, because it no longer contains the MIME type for JSON in a standardized format. Assuming the server responds with the same string for Content-Type, any application that does not know specifically about this API can no longer recognize that it's JSON and, e.g., pretty-print it for a user, as I haven't seen done for JSON but is regularly done for XML by browsers.
On the other hand, the original suggestion:
> Accept: application/json
works in theory, but in practice makes it more difficult to test the API in a browser. This is not the end of the world, but there does not seem to be any real benefit in using Accept. I cannot think of any practical situation where a tool can use the standardized header for an advantage...
Having your clients send an application specific MIME type can actually be better for browsers as well. All you need to do is provide a representation of your resource in HTML which browsers will request by using "text/html" in the Accept header.
I've found this a nice addition to documentation and, depending on how well the HTML representation has been done, is great for learning/exploring an API.
I've personally given up trying to save the term REST. It was hijacked and will never recover completely at this point. What I've been looking for is a good alternative name. Sometimes I'll write out representational state transfer which is clever enough to get past most REST pretenders but I have yet to find something short.
I guess I should clarify my statement. The article is right on the dot. The point here is that arguments like this really need a new label. That's all I'll say.
I meant this to apply in general. Rather than try to correct people we should introduce people into the architectural style and since REST already means something to many, it only seeds confusion.
While I generally agree with the principles underlined in the article, using the Accept-Language header is definitely not the right way to control internationalization.
Remember that one of the advantages of URLs is the ability to easily share them, however I'm not sure I'd be comfortable sharing content that could show up translated to some recipients, based on the language of their browser/application/computer. For example, most CMS systems assume that the content can be completely different between languages (for the same article): you can have the full text in English and only a teaser in other languages.
Maybe not a pure REST approach but using '/en','/pt','/fr' in the URL has proven to be much easier and safer, from my experience.
It depends on what content is translated. I think that Accept-Language is OK for UI elements - seeing 'entrar' instead of 'log in' and elements like that. For actual content, probably not.
One thing that I cannot find mentioned neither in the article nor in comments, is the confusion related to the idea of state.
While REST is, by definition, stateless, it merely describes the session, not the manipulated data. There's no way to avoid, at least implicit, object's state. For example, if user's password is not empty, it means that the user already set the password.
More comprehensively, with /users/1/edit, or whatever, it is frequently expected to get a different validation error, depending on the flow, such as a paid account might require more billing related details than one without email confirmed.
Of course, it is a nightmare to maintain such matters implicitly. That's why Ruby on Rails plugins like acts_as_machine, and similar, come handy. They do provide an explicit description of the object's behaviour, easy to transform into documentation, depending on the current state.
The idea shows its full potential with multipage forms. Each step of the form might be described with a different state, stored in the state attribute, leaving the controller RESTful, and the model's validations easy to understand.
A yet another confusion comes with too close database mapping. To stick with Ruby on Rails, there is nothing preventing the developer from creating his own setters and getters, like def vattr=(); end; def vattrr(); end.
The framework passes the value of a virtual attribute, using params, to #update_attribute, and other methods, the same way it does for regular attributes created automatically from the database's schema.
Very frequently such attribute provides a much cleaner way to represent the model, rendering either the HTML or the API much more easier to write or understand.
Maybe not a news article. But for example, if you're seeing a user's profile with the UI in English, is it really a different resource that the same user's profile in German? I don't think it is.
If nobody understands REST, and as other articles have claimed, nobody does it right, then why do we keep trying to use it?
Switch to something simple that everyone can understand like JSON-RPC and quit worrying about pedantry.
good article but...he says version numbers in the url are bad but doesn't say why. using accept headers for versioning is a hassle for every client and makes browser based testing much more difficult. also a v1 user really might not be the same as a v2 user so they shouldn't be the same resource.
>he says version numbers in the url are bad but doesn't say why.
Because according to the spec, each resource is named by a single URL, so two URLs name two different resources. But if you put version numbers in the URL, you might end up with http://example.org/v1/rubyrescue and http://example.org/v2/rubyrescue, which according to the spec are two different users but in reality they're the same.
>also a v1 user really might not be the same as a v2 user
In what cases should the users be tied to the API version? I can't think of any.
"Because according to the spec, each resource is named by a single URL, so two URLs name two different resources."
I don't think this is technically correct. For instance, you might have a blog with a post at /blog/2011/07/03/why-i-love-rest and you might have /blog/current represent the same resource until you post something new. This seems like a valid case in which two different URIs name the same resource.
If you are versioning the resources themselves I think the version in the URI is perfectly fine. In reality this is almost never the case and people mainly use the version in the URI to designate different versions of the representation. This is bad since it ties the URI to the representation which is a big no-no.
Hmm, I think that those URLs are still different resources; one is 'the current post' and the other is 'the post named "Why I love REST"'. I would do a 302 from the latter to the former.
I don't have a 'problem' with it, this is just conceptual talk. But I'd still do it for SEO reasons.
If Google fetched /blog/current as containing the "Why I love REST" post and showed it to me, and the when I clicked the link I got "Why I think turtles are awesome", I'd be annoyed. A 302 fixes that in a more clean way than entries in robots.txt or similar tricks.
EDIT: Apparently Google messes that up and often associates the content with the source URL and not the destination URL. Disregard the previous paragraph.
good point, but the point of a restful resource is that the url represents a resource, but then w/accept header versioning, i now need two pieces of data, one of which isn't visible, to properly represent and retrieve a resource.
I guess my point is that if i have to pick, i'd rather occasionally have two request urls with a minor version difference that are actually the same resource than two urls that appear to be the same resource but are not because one was requested with a header that affects the returned data.
You're confusing resource with representation. An URL is a resource, but if the representation of that is a JSON document or a picture of him/her, that's up to the server. Just because an header affects the representation of a resource, doesn't mean they're different resources.
actually that's a good example that makes my point. if i said to you - well if you want to retrieve a person's user information, just GET /users/1 with Accept: text/json. If you want their photo, just GET /users/1 with Accept: image/jpeg - philosophically, i'm not violating the 'rules of REST' but it feels wrong to me.
Sure, I would create a "User's photo" resource too and link it from /users/1, but that's because a user's photo can be a new resource, so it can have its own URL.
yes i'm thinking more pragmatically. From an API perspective the header is part of the request but given that the human-readability of urls is a feature of http, it just somehow feels wrong to me to modify the response based on a request header.
I think most developers don't see that as a problem.
We modify the response all the time based on headers like User-Agent, Referer, If-Unmodified-Since, Accept-Language and others, so using Accept for versioning isn't really that strange.
iiuc, two resources can contain the same value, (http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch...) so you're not constrained by the number of identifiers with which you can reference a single entity. furthermore, it's debatable whether the versioned identifier hierarchy adheres to the principles of HATEOAS and discoverability, so practicality probably rules when implementing such an API.
Excellent article... We followed all of these Rest principals when we designed apis for HP cloud print (i think it will soon become public)..except
1) Representing all resources with noun - We had a tough time representing all resources with Noun. One of our APIs is
Post on \PrintJobs\ - creates a new print job
But printing can only start when all the data (content to be printed) is uploaded on the server. So client needed an API to tell the server that it can start printing..something like this..
\printjobs\1\print
\printjobs\1\cancel
one way we thought to avoid this was to have a represent it job state and client can change them like this..
\printjobs\1
Put : <job>
<state="print">
</job>
But there are cons
1. These were not actually states, these were actions(verbs)..because state would be initialized, printing etc..
so if client does Get after making it Put..it will get "printing" not "Print".
So we were tangling with keeping semantics clear and making it easy at the same time. Hence we went with these resources. Do you think it could modeled better?
2) When we think of versioning, we always assume that only the representation can be changed..why not behavior? Take for e.g. if api implementation changes but not representation..clients may be dependent upon the implementation (i know this is bad! since implementation details are getting leaked out from the API)
You can't satisfy the HATEOAS constraint by simply returning URLs in the JSON response from your API. The structure of the data is still tightly coupled to your own application, and so must be any client that can make use of it.
It is essential that RESTful applications be able to evolve independently from the client. To allow this, they must use forms of hypermedia generic enough to serve as the engine for all present and future versions of the application. If the client has any code specific to your app, then your app is not RESTful in any scope beyond its own.
I'm not convinced that the whole resource vs action thing is all that important to REST. It's an ideal that has been largely ignored in practice and the web has been quite successful without it. Contrast this with HATEOAS which has been the unavoidable reality of the web since day one.
Before he even discusses his individual points the author gives his definition of "bad," and the reason the other approaches are "bad." From the introduction:
> Let's talk about a few cases where either REST or HTTP (which is clearly RESTful in its design) solves a common web development problem.
> so they make up a partial solution that solves their given case but doesn't jive well with the way that everything else works
The problem is if you don't follow those constraints, but still call your system REST. The meaning of the concept is rendered useless by so many people abusing it without understanding what it means.
I don't understand the point of "uri":"/transactions/1". Isn't the new resource's URI already part of the response (in the Location: header)? It's sort of like saying GET /posts/show/1 vs. GET /posts/1.
It's redundant in that particular instance. But it's a representation of a resource. It might be nice to define the representation across your entire system so that when you grab a transaction resource with a GET later, it still has that URI in it. Or maybe not. But it's not obvious that this is a bad idea.
Content Negotiation is a critical part of REST APIs and it's my observation that most simply ignore or default to JSON in all cases. Good REST APIs allow the client to "choose" the mime type. Without this part of REST - you have no "representational".
On that topic, to rely on an 'Accept' header is pretty risky. That presumes the client will always have control over the headers. It is in my opinion always wiser to make the API determine mime type by extension (.html, .xml, .json etc).
This is a great article. One challenge I am facing now is both building a RESTful API, along with a UI that uses the API. The biggest question I have is the use of shebangs in urls with the ajaxy app. We must support IE so pushState is out, but shebang just seems like a hack. I think at this point I have no choice but to implement shebang but I wonder if there are any viable alternatives?
I've had this discussion about hundred times now. REST "standards" are as important and significant as brace indentation "standards". A big problem with REST is that it is NOT a canonical (or even important) standard, but rather a useful pattern than can be used to make things exposed via HTTP more intuitive. The evil side effect of this is that a metric crapton of architects/engineers are wasting fifty bajillion programming-hours arguing irrelevant details about who's doing it "right" instead of building useful software. You cannot do REST "wrong" and more than you can do software "wrong"... Folks who argue about the "right" way of doing software are usually "wrong" because they are focused on writing software instead of solving problems.
I understand your frustration but I think you are misguided. Standards (and their cousins, best practices) are important to think about in order to create diverse yet maintainable and inter-operable systems.
"A big problem with REST is that it is NOT a canonical (or even important) standard, but rather a useful pattern than can be used to make things exposed via HTTP more intuitive."
No, its not meant to make HTTP interfaces "more intuitive". HTTP clients are machines. They don't have intuition. When your web browser hits the HN front page, it isn't using intuition to figure out what links to display.
You can make an argument that for a particular web service, adhering to a particular principle of REST doesn't matter. But you have suggested that the principles of rest never need to be an important consideration for any web service, which I submit is plainly false.
I really dislike creating resources to represent transient actions. Not a big deal in the case of a bank transaction as that is something you could easily imagine needing to be stored for later retrieval. A different example is relating one social network friend to another or searching for specific people on the site. Those are things that, to me, are much more borderline and I would err on the side of not representing them as resources.
You haven't really explained why you don't like creating resources to represent transient actions. What's wrong with POSTing to /friend-requests with requestor=stanleydrew&requestee=mberning? There's no need to keep a log around if you don't have use for it.
It really is a good read, I need to digest it, but my initial reaction is that some of this isn't pragmatic. Versions in URLs makes for dead-simple routing in any framework. Also, many APIs are used in a way where you know consumers will create a resource without requesting it (or at least, not within the same session). So why return any location information (whether in a header or in the body)?
Ironic that the author's homepage (http://steveklabnik.com/) is a confusing pretend console that takes several seconds (on every visit!) to reveal useful information.
Rest was a really big deal in the Java web-app world for about a year...
It was back when early versions of Struts were 'the designated alternative', and in the bad old days of J2EE and JAX-RPC.
Then Java EE 5 came out, which solved large chunks of the pain that J2EE inflicted, JAX-RPC got replaced with the infinitely better JAX-WS and there was a new breed of web frameworks as well, which blew Struts out of the water.
About that time REST essentially became 'yesterdays technology, solving yesterdays problems'.
I find it interesting that the guy banging the REST drum is a Ruby fan. Has REST always been part of Rails? Or is it something that has crept in over the last couple of years?
Is there anything genuinely new here, or is it the same old story, some dude clinging desperately to an obsolete technology?
I want to know what part of the Java web world you are talking about exactly?
I just question the concept that REST is in anyway considered to be obsolete within the Java web world. Spring-MVC focuses more and more around this technology, and is also the delivery point for REST web services from spring; Struts 2 has slowly moved more towards RESTfulness; and additionally frameworks like Play have come around.
'...REST always been a part of rails?'
'...obsolete technology'
How is REST -- a set of architectural principles and constraints -- obsolete when you use it every time you browse to a web page? I feel people need to start treating REST more for what it is rather than an API or some library, or SOAP for that matter.
This is an excellent example of a spec being deemed more important than a useable system.
Frankly, I don't give a damn about the REST spec, and neither should you. When I see an API I want it to be simple and clear.
/getAllPages/
Hey, it's a verb and I've got a pretty good idea of what I'm going to get back
/getAllPageNames/returnType/JSON
Now I really know what I'm getting. The simplicity and usability of this structure absolutely trumps a spec compliant call that involves request headers and nouns.
If you're building a system that requires having read someones dissertation, you're not doing us any favors. Especially when it comes to an API. Keep it simple, stupid.
Remember that your understanding of what a URL 'is' or 'should be' comes from a great deal of technical experience. If you're not working day in and day out to make powerful tools accessible to people WITHOUT such experience, please stop programming. Really, get out of the pool. Whatever awesome knowledge you need to make a system work internally is invaluable, but your interfaces should make the world a simpler, more magical place.
In this string 'get' appears once. However, as an experienced dev, you know that this is a GET request. To you it looks redundant. However to someone trying to understand what will happen when they hit enter with this URL in their location bar it is meaningful.
The question at that point is naturally "But if you don't know that's a GET request then why are you using an API?"
This is the point I'm driving at. There are scores of underserved individuals who want to do interesting things with your website that go beyond your GUI, and they are just brave enough to read through your API docs.
Now, when I'm thinking about API design I have a big initial choice. Is this API for skilled developers who care about the REST spec? Or is this a tool for as many people as possible to get more out of my service than I have time to accommodate with features. This is where I will always say "I don't care about the spec." A really talented dev will read the docs, discover how my design works, and will write something cool on top of it. I can trust the hackers I know to make things work by hook or by crook. The same cannot be said for someone who really wants to extend my functionality but isn't a talented developer.
I feel it's my responsibility to produce a tool that can be used by as many people as possible. I don't want to make a high-end professional camera, I want to make a better point and shoot. I want to extend the abilities of people, not demand they gain a large skillset to use my new tool.
New programmers and enthusiastic users are always on my mind. These are the people who's preconceptions are that it should 'just work' and that if it doesn't it's my fault.
This is why I applaud decisions like Chrome dropping http://
It simply doesn't matter to 99% of the users of the product, and in fact makes browsers less friendly and more confusing.
If I can get my api to work like this, then I will:
'I want to see all the names of pages on mywebsite.com'
If I had access to a deterministic natural language parser then I'd use it. As such a thing doesn't yet exist, I try to remain as true to that ideal as possible.
The REST architecture may be less confusing than others, but it is far from simple.
But you still have to make a GET request and hence understand what that verb does - so you don't really gain anything - and now you're creating ambiguities for the API users. What if I POST to 'getAllPageNames'? It doesn't make sense, does it?
Personally, I'd say that if a developer can't be bothered to read the whole nine(!) verbs of HTTP, he shouldn't use the API. I mean, GET is described in just 11 lines!
And (s)he doesn't need to read your docs: the smart thing about the Uniform Interface described by REST is that the same verbs work on all services of the same architecture (in this case, HTTP). So that knowledge is generic and transferable.
In any case, it's your prerogative to design your API as you wish, but please don't call it REST if you don't intend to follow its principles.
I agree! Making such api make it really confusing. And what if one have to support other verbs. Then, One will end creating apis for each verb. A programmer who is using this APIs knows about HTTP and he knows about verb..making it explicit in the url will make confusing for most developers.
> The question at that point is naturally "But if you don't know that's a GET request then why are you using an API?"
Your efforts to build what you perceive as the more accessible API is appreciated. However please take the time to understand the alternate viewpoint, it might be useful sometime.
The whole point of REST is I mostly do not have to study another API documentation. The "uniform interface" is not a limitation, it is a feature.
I suspect you may be underestimating your user-base. If your website has useful enough content, somebody is bound to write a programmable interface, RESTful or not.
A better more "RESTful" approach might be:
The REST client would then be able to traverse the representation without making guesses at the URL, and if the end-point of '/authors:id' changes for whatever reason, the href would be updated accordingly.Pagination/large data-sets could be solved as well:
... and a bajillion other common RESTful API problems through better convention.I'd agree with the author that REST is misunderstood, but my opinion is that its misunderstood on the grounds that today's "REST" implementations are lame database serializations. The web has been doing this since the <a href/> tag was conceived, but for some reason, modern REST implementations left this out.
How do you get more info on the author if you only have this piece of information? Rails/ActiveResource guesses through convention: "/authors/2", but that might not be the case, which makes this approach very brittle.