tags:

views:

512

answers:

7

I browser around for a decent example of a simple, fully REST API, to no avail. Checked on stackoverflow as well. The best I've seen is this post. Despite this, I still don't get the point. Let's take an example of an application that we all know: wikipedia.

Suppose we want to create a REST API for wikipedia. We expect the following verbs:

GET /wiki/Article_name: obtains a specified page
DELETE /wiki/Article_name: deletes the page
POST /wiki/Article_name: creates a new page
PUT /wiki/Article_name: updates a page.

Fact is: when you use wikipedia with your browser, you don't use a REST interface to navigate it. I am pretty sure that when you update a page, you never use PUT (although you are technically creating a new revision of a page, so POST makes sense). Similarly, when you delete a page, the browser does not send a DELETE.

My questions are:

  • is REST also an interface "for the browser" or just for scripts ?
  • should we see the HTTP world exclusively through the eyes of a REST representation? are things like GET /foo/?page=bar&action=delete still a valid point of view, or horrible mistakes of the past never to be done again ?
  • should the web access and the REST interface be intermingled or separate? For example, suppose you have a AddressBook application. You can browse the address book with GET /people/, and with GET /people/1523 you obtain that single person information on the browser, maybe in a nice printable HTML. If you want to modify his card, you would do (RESTfully) PUT /people/1523, or instead have like PUT /api/v1.0/people/1523 ?
  • could anyone please convince Roy Fielding to get human and provide a "5 years old child" example for a decent (in his opinion) REST API, instead of complaining about what is not RESTful (in his opinion), so that all the world can follow through?
+2  A: 

You're soaking in it.

Yes, GET, PUT, POST, and DELETE are all RESTful calls. Most of the time, you're using GET or POST. When you go to a URL, a GET request is sent to the web server. When you submit a form, it may be a GET or a POST, depending on the element. However, DELETE and PUT are perfectly valid calls under the right circumstances, like WebDAV. The HTTP page might clear some of that up.

REST, for the 5 year old child, just means "The client sends a request to the server to change state (adding/replacing/deleting/retrieving some content, in the case of HTTP), and the server replies (possibly delivering content and status, possibly just status), and the conversation ends. There is no back-and-forth conversation. So almost ANY normal call to a web server is RESTful, be it from your browser, from JavaScript, or from telnetting to port 80 from a terminal program.

REST is usually used in contrast to SOAP, where a web service has the ability to describe itself and its API to a client, and web services can be discovered from directories. That's much more complicated. So for the most part, if you're not doing SOAP (and soap is so complicated you can't possibly do it without knowing about it), you're doing REST.

While I'm addressing contrasts, some buzzwordaholics will contrast REST to AJAX. They are completely orthogonal, and it is perfectly possible to use AJAX techniques to make REST requests or SOAP requests. AJAX, for the 5 year old child, just means having some software running in the browser (it might be JavaScript, but it could also be Java or Flash) make an HTTP request to the server and handle the response, instead of the browser itself, so the display doesn't change until that client program running in the browser decides to modify the DOM of the currently-displayed page.

As to your questions on whether GET is a good idea or not, "it depends". GET puts the entire reuqest in the query string. That means if that's a request the user wants to do again some time (say it's a search page, or a link to a specific blog post), it can be bookmarked. The downside is that the query string can only be so long, and it can lead to users bookmarking parts of a URL they shouldn't. POST, on the other hand, can send virtually limitless content, but you can't bookmark it or send a URL to a friend (or enemy, depending on the link). You have to use the right one for the situation. Sometimes you need the Philips, sometimes you need the flathead.

Your example of GET /people/1523 and PUT /people/1523 is perfectly valid, though difficult to do with a regular web server, which won't understand what you want PUT to do. "people" would have to be a program in some server-side language that could process the request. If you were using Java Servlets, it could be mapped to a Servlet of any name. It would be a lot easier to separate your HTTP request verb from your data operation verb, like GET /people/1523/get and POST /people/1523/update (or GET /people/get/1523 and POST /people/update/1523).

dj_segfault
I remember reading that you should never put verbs into the URL.
Stefano Borini
Why is it wrong to put a verb in your URL? Forgetting all this REST stuff for now, if you were going to write a server-side program to get the data for an employee, and another program to update the data for an employee, what would you call those two programs that would make sense, yet not contain any verbs?
dj_segfault
because the whole point of REST is that you have a limited set of verbs for CRUD operations, and every operation is done on nouns. The noun is given by the URL, and it represents a resource (whatever that means). It is clear that, if you put a verb in a noun, is no longer a noun, and you are violating the assumptions of the REST protocol.
Stefano Borini
OK, I took a look at the PHP manual and the Java Servlets API, and I now see that the REQUEST_METHOD is accessible in both (though oddly, the docs for HttpServletRequest.getMethod() doesn't list DELETE), so in either language, the app can act based on it. I understand now. Thanks.
dj_segfault
+1  A: 

Several modern browsers still cannot send any HTTP requests except of GET and POST. It blocks wider acceptance of REST. Although some work-arounds for browsers are available (see this presentation by David Heinemeier Hansson).

According to Tim Berners-Lee, URLs should be opaque (though there is some debate here), so things like GET /foo/?bar=baz HTTP/1.1 are perfectly OK as far as GET stays idempotent and safe.

Reusing URLs by accessing them with different media types is considered a good practice.

I think one may use RFC 5023 The Atom Publishing Protocol as the canonical example of a RESTful API (at least Roy Fielding commented on some issues related to it).

Andrey Vlasovskikh
+4  A: 

Partial answer:

are things like GET /foo/?page=bar&action=delete still a valid point of view, or horrible mistakes of the past never to be done again ?

Definitely the latter. As far as I'm aware, there's not even any debate on this point. GET requests should be idempotent. Using a GET to do a deletion is a terrible abuse of the web, and I will laugh pitilessly at whoever does it when the googlebot comes along and erases their database.

Keeping search engines from screwing you up is NOT the only reason not to do this, so don't get any crazy ideas about doing this just because you do it under authentication.

If you want to have a delete button, have a delete button. If you really, really want the button to look like a link, use javascript to make clicking on the link execute a post (or make the link GET a confirmation page, which is totally acceptable).

Doug McClean
As far as idempotency is concerned, I totally agree on what you say, and I am sure that anyone out there can properly agree as well. GET should _always_ be idempotent, both for bookmarking reasons and for caching reasons.
Stefano Borini
This is all correct, but you are sort've answering a totally different question. REST doesn't solve the problem of having GETs with side effect. After all he could have done `GET /foo/bar/delete/`, which has all the same problems, but is RESTful. His question is whether or not we should be giving up query params for REST.
TM
Not only idempotent, but *safe*. For example, `DELETE` is idempotent, but not safe.
Andrey Vlasovskikh
For the discussion query parameter semantics see a link to the debate on URI opacity in my answer.
Andrey Vlasovskikh
@TM, GET /foo/bar/delete/ is not RESTful just because it lacks query parameters.
Doug McClean
@TM Assuming GET /foo/bar/delete actually deletes a resource, it is not RESTful because it violates the semantics of Http GET. This confusion about urls being RESTful or not is completely bogus.
Darrel Miller
@Doug I really don't think that is what you meant to say :-)
Darrel Miller
Darrel, I agree, with you, I was disagreeing (perhaps with poor phrasing) with TM's claim that it was RESTful.
Doug McClean
+4  A: 

is REST also an interface "for the browser" or just for scripts

Both. In fact the Browser is actually an excellent example of a REST client. The fact that it only uses a subset of the HTTP interface does not violate the uniform interface constraint. POST is pretty much a wildcard verb anyway. Scripts are defined in the description of REST as "code download" and play an integral part of the REST interface.

Update: The uniform interface constraint of REST does not say "you must use all available verbs" to be RESTful. It says if you use a verb, use it to perform an action that is consistent with the expected behavior.

should we see the HTTP world exclusively through the eyes of a REST representation?

No. REST usually is done over HTTP, but HTTP has no dependency on REST. However, if you are building a web application then you should seriously consider choosing the REST architectural style for your solution. It may not be the right option, but it probably will be.

The request GET /foo/?page=bar&action=delete breaks the rules of HTTP and therefore breaks the REST constraint of a uniform interface. But it breaks HTTP first!

Update: In the HTTP spec RFC 2616 section 9.1.1 it states: "In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval." Performing a delete action using a GET is definitely breaking the rules of HTTP.

should the web access and the REST interface be intermingled or separate?

In my opinion, they should be the same. In fact XHTML is actually an excellent format to use to deliver both UI and API results. It is standardized, it is easily parseable, it is viewable in a browser for debugging purposes, it can support hypermedia, microformats can be used to do semantic markup, class attributes can be used to define things that microformats don't cover. What more could you want?

If you are planning to do a HTML UI, why do the same work twice?

Can Roy give us a simple sample?

Read the How to GET a cup of coffee article to get a good idea of how a REST API should work.

When reading the article remember this important fact that everyone seems to have forgot:

REST interfaces should be EASY TO USE, they are NOT EASY TO DESIGN.

Darrel Miller
Stefano Borini
I addressed your first two issues by editing the post. 3) As for never using xhtml as an API format, well that is your loss. As for being difficult to parse, huh? Any XML parser will parse XHTML. XHTML has far more semantics than application/xml and application/json that have absolutely no semantic meaning.
Darrel Miller
4) I presume you meant to say, you cannot DELETE any object on the web. Well, POST's behaviour is not strictly defined by HTTP so you can use POST to delete. There are a number of accepted conventions to tunnelling DELETEs over POST using the x-http-method-override header, and javascript and XmlHttpRequest in the browser can be used to do PUT and DELETE. You seem to be stuck on the idea that the only valid REST interface is one where GET, PUT, POST and DELETE are mapped to CRUD operations. This is just not the case.
Darrel Miller
+1 for the very interesting answer and the cup of coffee article. Very good indeed
Stefano Borini
+1 for the very interesting answer and the cup of coffee article. Very good indeed
Stefano Borini
+2  A: 

Remember - REST is nothing more than a set of architectural constraints for distributed computing, independent of any underlying transport protocol. When evaluating the RESTfullness of a client-server interaction, you're really checking to see if one or more of these contraints are broken.

is REST also an interface "for the browser" or just for scripts ?

When you browse Wikipedia with Firefox, you're controlling a REST client. The lack of support for PUT and DELETE doesn't detract from the RESTfullnes of the interaction because the meaning of HTTP verbs is outside the scope of REST. A more questionable point might be the way that sites and browsers support sessions. When each request must be understood in the context of a session, you could say that the constraint of statelessness of requests is broken.

should we see the HTTP world exclusively through the eyes of a REST representation? are things like GET /foo/?page=bar&action=delete still a valid point of view, or horrible mistakes of the past never to be done again ?

AFAIK, this doesn't in itself break a REST constraint, unless the same URI/verb combination does two different things. In that case, you'd be breaking the uniform interface constraint. I'd say this approach is bad from the perspective of deviating from the intent of the HTTP protocol, but not from the perspective of REST.

should the web access and the REST interface be intermingled or separate? For example, suppose you have a AddressBook application. You can browse the address book with GET /people/, and with GET /people/1523 you obtain that single person information on the browser, maybe in a nice printable HTML. If you want to modify his card, you would do (RESTfully) PUT /people/1523, or instead have like PUT /api/v1.0/people/1523 ?

I don't see a problem with a RESTful API working differently for browsers and for other REST clients. The most important thing is to provide consistent behavior across a class of clients. API versioning is beyond the scope of REST.

could anyone please convince Roy Fielding to get human and provide a "5 years old child" example for a decent (in his opinion) REST API, instead of complaining about what is not RESTful (in his opinion), so that all the world can follow through?

This was exactly how I felt after reading that post and coming up against the near total lack of real-world examples.

Darrel Miller's suggestion for the cup of coffee article is a good one. If you want to get even simpler, just go back to your initial example - the browser. Every kid I've seen using a Web browser quickly understands how it works. You start on some page. You find something you like. You follow the link. You get to another page. You find something you like there. You follow that link and get to another page. And so on.

It's funny how hard it's proven to reduce this simple idea to practice for non-browser clients. For inspiration, you might check out the Sun Cloud API.

Rich Apodaca
+4  A: 

EDIT1: As I see the world, for most programmers REST as a concept is going to be a consideration when creating APIs. So REST is on your to-do list when you're creating an API for consumption by machines; NOT when you're talking about webpages that humans will interact with through a browser. EDIT2: And that does not imply that the browser isn't RESTful (it is). I merely mean that where the current action is, where most of the worlds programmers (those who don't work for a browser maker) can benefit from REST is mostly in web services.

Let's take an example of an application that we all know: wikipedia.

OK, but it's not the best example -- Wikipedia is a rich website, i.e. it has rich content made for humans not computers.

GET /wiki/Article_name: obtains a specified page

DELETE /wiki/Article_name: deletes the page

POST /wiki/Article_name: creates a new page

PUT /wiki/Article_name: updates a page.

Your datastructure is based on the human usage model for Wikipedia, hence the confusion.

I'm providing a quick example of an API for Wikipedia below, hopefully it will help illustrate my point. It's made very quickly; and I do not claim it to be a good API design. :-)

Note 1: In the below API example, I'm using JSON. As far as "RESTfulness" is concerned, it does not have to be JSON, any data format that can be meaningfully exchanged via HTTP is fine. So other examples could be XML, TXT, JPEG, AVI. Broadly speaking, "RESTfulness" applies to the URL and HTTP headers, not to the page body -- the body is left free for the specific implementations needs.

Note 2: I'm pretending that Wikipedia has a internal, structured data format that gets transformed to HTML pages -- just for the sake of illustrating my view, as Wikipedia isn't really the best example to work with...

A first shot at a RESTful API for Wikipedia could be something like:

api.wikipedia.com/search/keywords

Takes a GET with search words in the URL, returns a JSON dataset of page IDs, page titles, URLs, and relevancy scores.

api.wikipedia.com/article/id/

Takes a GET, DELETE, POST, PUT, and will operate on the article with internal ID equal to "id" in the URL. Depending on the HTTP method of the request, it will:

  1. GET; return article (in Wikipedia's predefined, JSON based data format.)
  2. DELETE; delete article
  3. POST; create new article (article must be in the request body, in the predefined JSON format)
  4. PUT; update article (and whole page must be sent anew in the body)

api.wikipedia.com/media/id/

As the "article" endpoint above, but for CRUD of media such as images. .. and so forth, until all the needs of this imaginary Wikipedia API are met.

A quick glance at the imaginary API above reveals a number of problems .. and that's the beauty of REST; it is simple and does not get in the way of visualizing the data exhange.

is REST also an interface "for the browser" or just for scripts ?

EDIT3 Original text was: It is not intended for the browser, it is only for APIs intended for consumption by other clients or services that are 'machines'.

I'd like to change this to: The browser is RESTful. It is also a given, i.e. with the installed base, and the extreme amount of time it takes to get IE6 replaced, it is clear that the browsers we have today are going to be with us for a long time. And current browsers don't do anything with special with microformats or sites with XHTML for page rendition and XHTML for data transfer, they leave all that for you to do yourself via Javascript.

Thus, with current technologies, most of the new development that applies REST is in building better web services APIs. And practical considerations will make people choose to put their web service API on a different URL than their main website.

Relative to other web service technologies, REST has a significant advantage in the ease of debugging. You can just fire up a client on your PC, send a URL, and see the response right away. (OK, the same applies to some extent to many of the XML based web services; but machine-generated XML is impractical for me to 'read'.)

should we see the HTTP world exclusively through the eyes of a REST representation?

Ehh, no. The browser handles, what, 97% of today's website traffic on average?

should the web access and the REST interface be intermingled or separate?

Separate, in the example above I used api.wikipedia.com to illustrate that it's completely separate from the regular Wikipedia site. For practical considerations, such as load balancing, different release schedules, different business requirements.

Jesper Mortensen
I don't know if what you expose is correct 100 %, but it is clear, to the point, and insightful. Thanks!
Stefano Borini
As per Roy Fielding's dissertation (section 5.2.3) one of the key REST components is the "user agent"... "the most common example is a web browser" Could you clarify where you got the idea that REST is only for consumption by machines?
Darrel Miller
Jesper Mortensen
A web browser is already a RESTful client, it does not need to change to support REST interfaces. I personally find it offensive that you feel justified in hi-jacking the REST term and applying your own definition that is inconsistent with the original author.
Darrel Miller
Oh yeah, and regarding the web browser not changing. See the Html5 spec http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#form-submission PUT and DELETE will be supported in HTML5 forms. Which in reality means Opera 9 already supports it.
Darrel Miller
@Darrel Miller: I changed the wording at EDIT 1 to 3 to avoid hijacking the term REST, as you correctly said that I did. I hope this make my intentions more clear.
Jesper Mortensen
Ok, I can accept what you are now saying. It is an unfortunate situation, but it is reality.
Darrel Miller
The POST URL should not include an ID: POST creates a subordinate resource *under* the resource to which the POST is made. So, rather than POST /article/id, one would use POST /article/, and the response would be 201 Created, with a Location header pointing to /article/id, the id being specified by the server. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
NickFitz
A: 


1. NerdDinner uses WCF Data Services, which is a great way to correctly implement RESTful services. The reason I am point to that, and not WCF data services directly is because it is a public website and you can use it. 2. MediaWiki is not a great example because they are passing actions in the URI but it is technically a RESTful service and show's a lot of interesting ideas.

Robert MacLean