Skip to content

Instantly share code, notes, and snippets.

@CrookedNumber
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CrookedNumber/8978018 to your computer and use it in GitHub Desktop.
Save CrookedNumber/8978018 to your computer and use it in GitHub Desktop.
RESTful

The short answer is that no one talks about RESTful websites because websites are RESTful by default. You really have to try to make a non-RESTful website (though it has been done--see below).

The setup you're describing takes a lot of elements from REST, but it's not "REST" per se: it's a set of conventions designed for the convenience of server-side programmers. Most of today's web APIs only use a subset of the REST constraints, and it's a subset that doesn't include the main driving principle behind websites.

Let me back up a bit. Here's what websites and web APIs have in common: they both expose functionality through resources. Each resource is identified by a URL, and each responds to an appropriate subset of the standard HTTP methods. (This may seem obvious, but look at XML-RPC or SOAP, where there's only one URL for the whole system.) A resource might send documents to the client (in response to a GET request) and/or it might accept documents from the client (along with a POST or PUT request).

Now, the differences. Web APIs often map the four most common HTTP methods (POST, GET, PUT, DELETE) onto the four CRUD operations (Create, Read, Update, Delete). Web sites can't do this, because web sites run on HTML, and HTML forms only support two methods: GET and POST. And yet, a web site can easily describe all sorts of actions--"search", "next page", "purchase", "unfriend"--which are nontrivial to map onto CRUD.

That's because HTML supports links and forms. This is what's missing from the "Web API" branch of the family tree. Not the resources, but the machine-readable connections between resources. (To drop some REST jargon, this is "the hypermedia constraint" or "hypermedia as the engine of application state.")

"Web APIs" tend to ignore the hypermedia constraint because a) it's difficult to understand, and b) JSON doesn't support links or forms, so it's difficult to obey the hypermedia constraint even if you want to. (This is changing with the development of formats like JSON-LD, Hydra, and HAL.)

But the hypermedia constraint is literally what holds the Web together. Take away the links and the forms, and you'd be left with an unusable mess.

Python Challenge is a good example of a non-RESTful website. You get a starting URL and then you have to solve a little puzzle to figure out how to get to the next URL in the sequence. You still have resources, and each resource has a URL. But the connections between resources are obscured. This is fun as a game, but no one would run a serious website this way. Unfortunately, this is kind of where we are in terms of "Web APIs."

Further reading

As you can tell, this is a complex topic. At the risk of tooting my own horn, the "maturity model" I developed for a 2008 talk might help you understand the architectural difference between the World Wide Web (level 3) and most of today's APIs (level 2). I'd also recommend Steve Klabnik's Designing Hypermedia APIs, and my own RESTful Web APIs, which starts out by comparing a web API to a website that does exactly the same thing.

My earlier book, RESTful Web Services, also covers this topic, and it's free to read online. However, it's somewhat out of date (it was published in 2007), and in retrospect I don't think it pushes the hypermedia angle hard enough.

Miscellaneous

To briefly respond to a couple of minor points from your original question:

There is no technical difference between a web API and a website. A website is a web API that happens to serve HTML documents.

One URL is not more "RESTful" than another. This is solely a usability issue. On a technical level it doesn't matter at all what your URLs look like. /users/login.json and /login and /the-first-100-prime-numbers.gif are all equally RESTful ways to refer to a login form.

The home page is a resource: it's a "home page" resource. Its job is to contain the most important bits of information, and to guide the client to other pages--either directly through links, or indirectly through a search form. A resource does not necessarily correspond to a row in a database or an object in an object model. A resource can be absolutely anything, even a real-world object or an abstract concept. The only restriction is that a resource must have a URL.

/login is a URL, so yes, it identifies a resource. What kind of resource? If it's a typical scenario where sending "GET /login" gets you an HTML page with a login form, then it's a "login form" resource. If filling out the login form triggers a "POST /login" request, then it also acts a "login form processor" resource.

You might have better luck thinking of a resource in terms of the code that runs when a request for its URL comes in, rather than trying to map it to one particular "thing" in your dataset. That is, instead of trying to figure out what a resource is, think of it in terms of what it does.

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment