Hacker News new | past | comments | ask | show | jobs | submit login
The Restful CookBook (restcookbook.com)
149 points by brudgers on May 24, 2015 | hide | past | favorite | 47 comments



I just started at a new job, at a new startup.

During the my first job interview with them, they asked, "Do you know how to work with a RESTful interface?" I said yes, and I told them to look at my Github account for examples.

During my second job interview with them, they asked "What do you consider when you are designing a RESTful interface?" I quoted a bit from the book that Sam Ruby and Leonard Richardson wrote, back in 2007, and which I've read cover to cover. Among other things, I said the overall goal should be to work with HTTP, not against it. Then their lead programmer tried to ask me what he apparently thought was a "trick" question. (He was quitting the startup to go back to school, and I was being hired to replace him.) He asked, if, for a given task, HTTP was too verbose a protocol, then what else might I use for a RESTful interface. I suppose that should have been my first warning. I wasn't sure what they were looking for, but I thought maybe they wanted me to say WebSockets, or perhaps they wanted me to push back against the question and ask why HTTP was too verbose, or they wanted me to suggest the use of TCP in an ad-hoc style that mimicked HTTP. I explored all those possible answers as I spoke with them.

Then I was hired and I started the job. Their system is not RESTful at all. The only HTTP verb they use is POST. They use it for everything, and they put all their data in the body of the POST. Their system is pure RPC, with a style influenced by SOAP.

The people I'm working with are in their early to mid 20s. I'm not sure if age is a factor, since I've seen the same mistake made by programmers in their 50s. But, for sure, there are some programmers who do not seem to know the difference between RPC and RESTful.

Of course, on a personal level, none of that really matters. I really like this place that I'm now working, and I'm happy to work with their RPC style. I have, however, insisted that we use correct terminology, just for the sake of clarity.


I've seen that, and even been "guilty" of it myself years ago - many people take 'RESTful' to just mean anything that returns JSON instead of a full HTML document.


I usually use the term "REST" instead of RESTful - I know and understand the benefits of pure REST but I choose JSON over XML every time I can. Not to mention suboptimal support for PUT / DELETE / ... methods in Apache.


REST is an architectural pattern that specifies properties about the interface, not the data - how does using JSON over XML make your interface not RESTful? In his dissertation[1], Roy Fielding always refers to data in terms of resources rather than specific formats.

[1] https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...


I think the idea that JSON isn't "REST" is because, unlike XML, it doesn't define links.

That said, JSON is just an encoding format. The actual response format is not "JSON", but the specific structure that your clients are expecting to receive (even if it is encoded in JSON), and that can certainly have links.


To a good number of people, "REST" means the Web—but not SOAP. Mapping CRUD to HTTP methods, and so forth, completely escapes some people.

"REST good. I want." That's as far as some thinking goes :-(


> Their system is not RESTful at all

IHMO ,The problem is nobody has a clue what REST or RESTful really means,at least I don't. But it's clearly not a protocol. It's not even a well defined pattern that exposes clear behaviors with rules. Some developers don't like that, they want clear goals to do their work and want canonical examples they can point to when arguing with colleagues.

So personally I understand the appeal for RPC : No semantics , no arguing about whether one should use PUT, POST or PATCH and when , whether links should be headers or in the body, or about which JSON/XML bloated spec to use to make an API HATEOAS...


REST is well defined, it's just that most guides don't explain it well. REST is just a list of 6 possible characteristics of network protocols/architectures (Client/Server, Stateless, Cache, etc), and an explanation of the benefits gained by having them.

That said, it's true that REST by itself doesn't tell you how to build an API. But all of that arguing about PUT/POST/PATCH, links here or there, etc, are mostly bikeshedding. It's like arguing for tabs vs spaces or whether the { should go inline or not. Just read the HTTP spec and then, when in doubt, just pick one and try to be consistent.

But you're right that many programmers don't deal well with that. It'd be nice to have some kind of reference protocol using HTTP & JSON and complying with REST, even if it would be as arbitrary as any other possible RESTful protocol.


Whenever I see a REST book I always have the same set of questions:

1) How do I call operations such as Clean, Restart etc not the regular CRUD ones? I may have to end up doing a variation of POST - is that RESTful (whatever that means)?

2) Whats a good way to simulate a "transaction" semantic (In as much as possible over a distributed systems with arbitrary nodes i.e. the Web)

3) How Do I call a long running operation- a create that takes more than a minute for example? Return a "tracking id" and keep GET querying?

4)How do I version my API? What is the one true way?

5)How about automated discovery of the API? Is it SWAGGER or WADL or something else?

6) Is a nested hierarchical URL scheme a good Idea? How much do you nest one resource under the other?

7) Are you a Teapot?

Many other questions that I have never seen answered properly


1,2,3) Strictly, they are all resources. A "Clean" resource can be created (POST|PUT) describing what to clean. It will create (201) that resource which you can read (get the status), even delete (cancel the action), or change (POST/PUT) again. Take a look at the http://restcookbook.com/Resources/asynchroneous-operations/, which basically describes this.

4) According to Roy Fielding, you don't (you don't version your website), but you can add/change/delete your resource versioning. I'd (and many) prefer the accept-header for this, but there are as many different versioning systems as there are API's.

5: hypermedia / HATEOAS

6: sure. If it makes sense. Not everything is hierarchical, but things that are, do it.

7: 418

The reason for this was figure out myself how certain things should be done in a "restful" way. To be honest, truly restful is an utopia imho, but on a daily basis, I see many advantages (as well explained in Roy fieldings dissertation) about the restful setup in comparision to a non-rest setup.

Pragmatically, since I'm not building API's for HUGE system (and even if they are or will become so), it's still possible to use non-rest components (yes, even verb-like systems and url versioning like /api/v1/.

I consider rest to be like the pirates code: not so much a strict law, but more as a guideline.


Just today I read about postgrest[1], REST-like API for postgresql.

While it is not REST by what this cookbook says (it uses JSON), it provides very different view at how API should work.[2]

Postgrest versions the API using HTTP accept header. It provides "pagination" not using XML attributes, but using HTTP range headers, as the standard allows to specify partial content in items, not just in bytes. The author also suggest that deeply nested URLs are a bad idea, because most data (like relational data) is actually flat.

It might provide interesting "second opinion" to what this cookbook says. It doesn't say anything about transactions,

[1]: https://github.com/begriffs/postgrest [2]: http://begriffs.com/posts/2014-12-30-intro-to-postgrest.html


>HTTP range headers, as the standard allows to specify partial content in items, not just in bytes

When doing HTTP Range requests, you'd use HEAD to get the complete length first. If your range requests are in items, is it still in spec to specify Content-Length in items too? I'd think that would break some clients.


Add:

8) How to represent relations (esp. many-to-many) between non-hierarchical resources? The answers I have seen are either variations of "represent the relation as a resource" (is tying the relation resource's lifetime to that of the things related RESTful?), or "represent the relation as a property on both resources" (is it RESTful to reflect the update of a property on one object in another?).


Fascinating that even here on Hacker News, where we can presume the audience is well-informed about tech matters, the comments on this post show a large amount of confusion about the definition of "RESTful". I see some comments raise the issue of XML versus JSON, as if the encoding format impacts on whether something is RESTful. I see others raising the issue of HATEOAS, with some comments suggesting that RESTful is HATEOAS, and others suggesting that RESTful is a different approach from HATEOAS.

A term that lacks any agreed upon meaning is of no value. But I wonder why the meaning has become so blurry?

I was under the impression that the bible on this subject was the 2007 book by Leonard Richardson, Sam Ruby (and a nice forward by David Heinemeier Hansson):

RESTful Web Services

http://www.amazon.com/RESTful-Web-Services-Leonard-Richardso...

However, reading the comments on this page, I have the impression that many people here have never heard of that book.


When I read the title of the post, I wrongly assumed it linked to the "RESTful Web Services Cookbook", which is another O'Reilly classic on this topic. The advice I've heard is to read one or the other, depending on which prose style you prefer.

It's nice to see a CC-licensed effort to create a similar resource. It's unfortunate that the names are so similar.


While some of the tips are useful, I'd much rather see them written with JSON rather than XML. JSON has long been an industry standard. XML is bloated, almost no one uses it anymore.

http://restcookbook.com/Mediatypes/json/ says "There is no predefined way to deal with link discovery in JSON". I'm surprised it doesn't even mention JSON Schema (http://json-schema.org/) or JSON API (http://jsonapi.org/), which are not official standards but allow you to write machine understandable and discoverable API.

If the author wants to promote standards, I think it would be better to look at what the world is using and then put together a guide that explains how to use JSON-LD and other W3C proposals.


I think some of the articles actually talk about json-hal and ld. Not sure about schema.

The examples are in XML because json is, (and I believe at this point), still not stricly an (accepted) hypermedia capable format, thus not adhering the HATEOAS constraint, and thus cannot be restful. But to be honest, I'd prefer JSON over XML anytime.

Please, if you have any idea's on how to improve the site, the whole idea was to set up a small set of articles which others could help out expanding. It turned out that not many people actually posted their idea's (or even complete posts), so what you see on the site is pretty much the same thing as 2-3 years ago. I'd love some more PR's on expanding with up-to-date technologies and techniques (even those who aren't truly restful)


> The examples are in XML because json is, (and I believe at this point), still not stricly an (accepted) hypermedia capable format, thus not adhering the HATEOAS constraint, and thus cannot be restful. But to be honest, I'd prefer JSON over XML anytime.

What exactly is the criteria of being a "hypermedia capable format"?

The linked website gives an example of how the response on a bank-account like API might include links to other actions; XML and JSON seem equally capable here, as they can both encode links.

He mentions on another page,

> Unfortunately, JSON is not a hypermedia format. There is no predefined way to deal with link discovery in JSON.

Is there a predefined way to deal with it in XML? In the earlier example, I had assumed he did exactly what you would do in JSON: make up a field for the purpose.

Though, honestly, that would seem to be the purpose of the "Link:" header.


> What exactly is the criteria of being a "hypermedia capable format"?

One document must be able to link to another.

> Is there a predefined way to deal with it in XML?

Yes, Xlink:

http://www.w3.org/TR/xlink11/

> In the earlier example, I had assumed he did exactly what you would do in JSON: make up a field for the purpose.

The problem with this is that it's non-standard and nothing understands it that isn't custom-written for that particular API.

> Though, honestly, that would seem to be the purpose of the "Link:" header.

Yes and no. Although the Link header is useful, it's not part of the document, it's a transport layer header. REST is transport-layer neutral.


There are a number of specifications that address linking in JSON:

  * JSON-LD http://www.w3.org/TR/json-ld/
  * HAL https://tools.ietf.org/html/draft-kelly-json-hal-06
  * Siren https://github.com/kevinswiber/siren
  * Uber https://rawgit.com/uber-hypermedia/specification/master/uber-hypermedia.html
Totally agree on the points against making up a field / format. Using standards where you can is a great way to bring familiarity & common tooling into your APIs. But don't focus too much on XML vs. JSON, use what you need / want, you can find a standard to support it.


HAL solves this issue pretty well, doesn't it?


> which are not official standards

It depends on what you mean by 'official standards.' We've registered JSON API with IANA, so it's a standard media type, but there hasn't been an RFC yet, as we're basically just finalizing the spec now. (We're in a week-long period of just textual review, conceptually and structurally, it's done.)

And given that AMS is going into Rails and Ember Data will default to JSON API out of the box, hopefully we'll have enough usage to actually justify an RFC in a year or so.


Great to hear that Steve!

We're actually moving towards the JSON API ~standard~ format and hope it becomes the standard that gets widely used.


Neat! :) And thanks.


Are you aware about anything resembling a convention or at least a limited consensus of best practices combining JSON Schema/Api with JSON-LD? That would be immensely useful.


"XML is bloated, almost no one uses it anymore." XML bashing is quite common these days. But I'd like to point out that it's the use case that matters when deciding between JSON and XML. Almost all "enterprise" software prefer XML over JSON.

https://www.quora.com/Markup-Languages/What-are-the-advantag...


I personally find XML more readable than JSON.


I think a huge drawback of XML is it can't differentiate between an element and an array of one. So to "read" it correctly you should read a schema, too.


It's weird to me that a cookbook exists for this, though if it's helping people I have no problem with it. I'm just not sure why we think of "RESTful APIs" as anything other than using HTTP to its fullest capabilities. Even HATEOAS is really just "hey, shouldn't our APIs be as easy to navigate as the rest of the web?".

I also find it ironic that there are lots of articles around condemning "the Web" for its idiosyncracies, the biggest offenders are JS folks complaining about how the DOM is implemented (disclaimer: I think it sucks too sometimes), yet these same circles champion things like "REST" and "HATEOAS" and "JSON API"...how are those things not part of "the Web"? Why do we only use "the Web" when we're pejoratively discussing it?

All that aside, this book seems relatively well-written. Good job guys!


This Software Engineering Radio podcast interview with Stefan Tilkov discusses the difference between REST and HTTP: http://www.se-radio.net/2008/05/episode-98-stefan-tilkov-on-...

It is from 2008 but probably more or less evergreen.


I'd like to request a "recipe" for handling authentication to my API. I want to know: what use is an API key? Should I be authenticating client apps separately from users? (That's users of the application into which the API reaches.) What are the tradeoffs of sending login credentials with every request versus using a token?

Maybe this particular cookbook isn't the place for it, but I'd really like to see something cover this. It's a problem that stumps me.


The purpose of API keys & tokens are to bring user authentication details out of every request. This is helpful in many scenarios:

  1.  API keys and tokens can be more easily replaced / canceled than entire 
  accounts in the case of being breached
  2.  API keys & tokens can commonly have additional access restrictions applied, 
  while it's hard(er) to do that for a whole account
  3.  Likewise, it's easy to think of many-tokens-to-one-account systems, 
  where you encourage users to use different keys for different integrations, 
  which helps lower the surface area of the damage one leaked detail can do
  4.  Many authorization protocols, like OAuth 2, rely on temporary tokens, 
  which are even more helpful in that they guide application integrations towards 
  not hardcoding sensitive details
Just a few reasons & justifications off the top of my head.


Having worked with hypermedia APIs recently I've come to appreciate how they feel more pragmatic and REST more pedantic. The hateos principle in particular lets you build thinner clients.


Isn't "hypermedia API" just a new name some people came up with for "REST API" because the misunderstood non-HATEOAS mangling of REST is so common and they wanted to distinguish between the two? Real REST APIs use HATEOAS.


Yes.

Strictly speaking, you can use hypermedia without REST, too. But that's the lineage of the last few years of what people are talking about.


So I'm a so-called "full stack engineer" and the definition I've internalized is that a REST api is essentially about modeling the entities in your application and defining what actions can be taken on each (with consistent use of verbs). And a "hypermedia api" approach is more about modeling behavior.

As an example, an api for AirBnB's mobile website might expose a /srp endpoint that can be used by a thin client to render the results recursively. Again, the way I've internalized it, to be a REST api I'd expect a client to request results from a /listings endpoint of some kind.

I think there is a lot of confusion and misunderstanding and that precise language is better for everybody. What should we be calling these things? I'd love your thoughts on it.


Your intuition is very good, and gets very close to the heart of the matter.

I think that the true heart of the hypermedia approach is actually "how do I deal with change over long periods of time in a scalable fashion?" Everything else flows from this. Exposing behaviors instead of data is one facet of the approach.

> What should we be calling these things?

Which 'these' are you referring to?


I only took a quick look at this, but the first thing I looked at was their discussion of POST vs. PUT. I worry about their answer. My understanding is that the fundamental consideration is idempotency, and what you would like that to do for you. I would have started the discussion there, and then added as a footnote the idea of convenience of working with resources. They seem to have done the opposite.


Client sends a request to delete item #12345 from DB. The item does not exist in DB. Is that a 404, because the resource isn't found, or just generic 400? 404 should be reserved for URL/route errors.

We need a few new error codes for common REST operations.


> 404 should be reserved for URL/route errors.

What dichotomy are you working off of here? It is absolutely a 404. How is this any less applicable to a DELETE request than it would be to a GET request for the same resource? What extra information would this new status status code carry?

----

> 10.4.5 404 Not Found

> The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10...


Ok, so client requests "DELETE www.company.com/api/thing/1234" and gets a 404. Or even "GET www.company.com/api/thing/1234". Delete vs get doesn't matter.

Did 1234 not exist, or is "/api/thing" the wrong path?

404 is overloaded. It can mean two very different things.


> Did 1234 not exist, or is "/api/thing" the wrong path?

This doesn't matter. You shouldn't be trying to pull "1234" out of the URI. The identifier for the resource as far as the client is concerned is the URI, not some numeric component buried within it. Just treat the URI as an opaque piece of information – if you get a 404, it's the wrong URI. If you're trying to divine meaning from the constituent parts of the URI, then you're almost certainly making a mistake.


Yes, but is it the wrong URI because the path is wrong (and then I'll double check the docs and my code), or was the 404 because the code is correct but the specific item could not be found? All you are saying is "it doesn't matter", which is unhelpful and ignores the fact that these are completely different error conditions.

All server code for REST will be written in terms of /path/to/{ID}. We have a path, we have a instance ID, which each may be incorrect.


> is it the wrong URI because the path is wrong (and then I'll double check the docs and my code)

This is the source of the problem. REST APIs are hypertext-driven. They use links, like the web. You access resources by following links, not by constructing URIs. If you are reading the specification to find out which paths to use, then hard-coding them in your client software, then you don't have a REST architecture, you have something very different (which, unfortunately, some people insist on calling "REST" anyway).

REST revolves around hypertext. You don't hard-code paths, the server provides resources that link to one another. The client accesses the resources by following the links, not by constructing URIs itself.

If you have a REST architecture, then you can't get the path wrong in your client code because the path isn't in your client code. It's in a resource the server gives you.

> All server code for REST will be written in terms of /path/to/{ID}.

Perhaps, but the client should not be aware of this. The ID that a REST client uses is the URI.

> We have a path, we have a instance ID, which each may be incorrect.

The only ID that the client has is a URI, and if you get a 404, it means that there's no resource available for you to access with that ID. The client does not have a path, and the client does not have an instance ID. It only has a URI.


Ah, I think I understand what you're getting at now, that's a really interesting question.

I can't entirely back this up without probably days of reading RFCs, but my initial gut feeling is that making this distinction, which is not really possible in a truly general way (provided the URI is a syntactically correct HTTP URI), would be exposing internal implementation details in a way that would be conceptually inconsistent with other HTTP response statuses.

eg, how to usefully and consistently make the distinction:

    GET /asfd
    200 OK

    GET /qwer
    4XX We don't have that right now

    GET /zxcv
    4XX That is not even a thing
Keep in mind that the RESTful URI style is not part of the HTTP standard in any way. In HTTP, URIs can be random gibberish, even if they refer to "sibling" resources semantically. "You're on the right path" vs "What are you even talking about" is not an inherent concept in HTTP.

It might make sense in certain circumstances of RESTfully-modelled resource URIs layered on top of HTTP:

    GET /users/asfd
    200 OK

    GET /users/qwer
    4XX We don't have that right now

    GET /blarghs/asdf
    4XX That is not even a thing
But to describe this situation in an HTTP response status would be "mixing layers" and making assumptions in a way that opens a conceptually messy can of worms.

----

Disclaimer: I have no idea what I'm talking about and am not entirely convinced by my own argument. I'm always skeptical of "that's just not how it's done right now"-flavoured arguments, which this doesn't stop smelling like as I attempt to reason about it.

----

As practical matter, the body of the 404 response can describe the situation within the context of the application. And if your application is smart enough (though to do this in the general case is impossible or would require something like strong AI), you can use any of several more specific responses (Gone, Found, etc; depending on the context) if you're willing and capable of inferring a specific intent from the otherwise bad request.


"is /api/thing the wrong path" - is fixed by hypermedia, so 404 generally means that resource cannot be found.





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: