Monthly Archives: November 2013

The future may just as well be RESTful

Chris Zheng has just published an article on “Why the future is NOT RESTful”. It made a bit of a splash, but I think it’s based on false assumptions and quite wrong. Here’s why.

Chris observes that client takes more and more responsibilities from the server. He suggests that server is slowly becoming just a database frontend with authorization. I think it’s very wrong if not dangerous.

Server will never be a dumb database frontend except for trivial CRUD applications. If you have more than one user in the system working with the same thing concurrently, you have to have some coordination on server side. If you have any business logic at all, you have to have it on the server side.

Client is becoming thicker, fine. It may have a database, offline state and a lot logic. But it does not mean that server is losing any of its thickness in domain model. We’re only moving the presentation side (all of it), enhancing it, maybe duplicating the domain logic. But ultimately we cannot trust the client about anything. It’s all in hands of the users, exposed to reverse engineering, all kinds of forgery and so on. I can send whatever I want to the server with curl.

Next point: With REST you can’t have security. I’m young, green and new to the game, but is that really true? Does REST mean no authorization, no results filtered for each user? If Jim can see some “accounts” in the system and Jessica some others, does it make it impossible to return different results for GET /account depending on context?

To take it a step further: We’re not talking about the very monolithic view here, are we? REST doesn’t mean that you only can have one representation of an “account”, and only one GET/POST/PUT on it. You can still have more representations, each tailored for a specific use case. Getting a list of Jimmy’s friends would be a completely different endpoint from managing user permissions, account settings etc. Even if they’re all “accounts”.

Another point that Chris is making is that for some reason having one resource for one thing is bad, but there’s little explanation for it except for a restaurant counters analogy. It’s hard to argue if there are no real arguments on the other side, but…

Having concrete, well-defined resources that represent one thing each doesn’t really sound like a bad idea to me. If anything, it’s more like the ideal interface segregation and single responsibility. Are they not desirable anymore? Going back to blurry restaurant analogies – I may go for fries or rice, I do order dessert from a different part of the menu than the main course, I may even order wine from a different menu altogether. I may be served by more than one waiter. Heck, sometimes I may even go for a buffet!

To sum up, REST is more than dumb CRUD, and server is much more than just an authorizing database front end. Popularity of REST is a bit of fashion, it’s just another way to solve the problem, and by no means is it the silver bullet. But still, the future may just as well be RESTful.

“Beautiful REST + JSON APIs” by Les Hazlewood (notes from the talk)

Here’s a summary of a few interesting technical details from a very good presentation on designing REST APIs by Les Hazlewood. Many interesting, elegant and not so obvious solutions here.

  • Keep resources coarse-grained, especially if you’re designing a public API and you don’t know the use cases.
  • Resources are either collections or single instances. They’re always an object, a noun. Don’t mix the URLs with behavior. /getAccount and /createDirectory can easily explode to /getAllAccounts, /searchAccounts, /createLdapDirectory…
  • Collection is at /accounts, instance at /accounts/a1b2c3. Create, read, update and delete with GET/POST/PUT/PATCH/DELETE… Everyone knows, but anyway.
  • Media types:
    • application/json – regular JSON.
    • application/foo+json – JSON of type foo. In my understanding, roughly corresponding to XML schema or DTD.
    • application/foo+json;application – JSON of type foo, where the response type (entity format?) is application.
    • application/json, text/plain – JSON prefered, text acceptable.
  • Versioning:
    • https://api.foo.com/v1
    • Media-Type application/json+foo;application&v=1
  • HREF:
    • Use instead of IDs
    • Sample use:
      GET /accounts/a11b223
      200 OK
      {
        "href": "https://api.foo.com/v1/accounts/a11b223",
        "givenName": "Tony",
        "surname": "Stark",
        "directory": {
          // Instance reference
          "href": "https://api.foo.com/v1/directories/ffb554"
        },
        "groups": {
          // Collection reference
          "href": "https://api.foo.com/v1/accounts/a11b223/groups"
        }
      }
      
    • Reference (link) expansion:
      GET /accounts/a11b223?expand=directory
      {
        "href": "https://api.foo.com/v1/accounts/a11b223",
        "givenName": "Tony",
        "surname": "Stark",
        "directory": {
          "href": "https://api.foo.com/v1/directories/ffb554",
          "name": "Avengers",
          "creationDate": "2013-08-08T14:55:12Z"
        }  
      }
      
    • Partial representations:
      GET /accounts/a11b223?fields=givenName,surname,directory(name)
      
    • Pagination:
      GET .../applications?offset=50&limit=25
      {
        "href": ".../applications",
        "offset": 50,
        "limit": 25,
        "first": { 
          "href": ".../applications?offset=0"
        },
        "prev": {
          "href": ".../applications?offset=25"
        },
        "items": [
          {"href": "..."},
          {"href": "..."}
        ]
      
  • Many-to-many – represent as another, special resource, e.g. /groupMembership. Not so obvious potential benefits: If you make it a resource, it’s easy to reference from either end of the association. If you want, you can easily add data to the association (e.g. creation date, responsible user, whatever).
  • Error handling – credit to Twilio.
    POST /directories
    409 Conflict
    {
      "status": 409,
      "code": 40924, // because HTTP has too few codes
      "property": "name",
      // Ready-to-use user-friendly message:
      "message": "A directory named Avengers already exists",
      // Dev-friendly message, can be stacktrace etc.
      "developerMessage": "A directory named Avengers already 
        exists. If you have a stale local cache, please expire
        it now.",
      "moreInfo": "http://foo.com/docs/api/errors/40924"
    }
    
  • Security – many interesting points here, but one particularly valuable. Authorize on content, not URL. URLs can change and may diverge from security configuration…

It’s too bad that the presenter doesn’t really leave the happy CRUD path. I’d really like to hear his recommendation or examples on more action-oriented use cases (validate or reset user password, approve order, what have we).

The entire presentation is a bit longer than that. I talks quite a lot about why you would want to use REST and JSON, as well as security, caching and other issues.