Sunday, 29 September 2013

REST Frameworks

I keep on coming back to this topic, in a variety of different languages, and I keep on having the same problems. I can never find a framework for writing REST first services that actually works how I want it to work, and will scale to a reasonable sized application.

One thing that I find remarkably common is frameworks that want to define every single route in the entire application in the same place, instead of some structure for how these are defined. This works well enough in small applications, where you have a small enough number of routes that you can manage this, but by the time you get to a couple of dozen routes - which really isn't that many when you sit down and think about it - it starts to get unwieldy.

So - in my ideal REST framework, which I might end up actually writing myself at this rate - these are the features that I would look for, in no particular order:

  • Sane route management. I quite like the way that Grape works here, where you define handlers in a class that are all related, and then you mount these classes on specific endpoints. So, to take the traditional blog example, you would have one class that provides all of the handlers related to posts and mount that on /post. You would then have a different class that provides all of the handlers related to users and mount that on /user. This keeps things nice and separated out, whilst still being easy to manage.
  • Support for selecting routes based on more than just the URL path and the Request Method. Selection based on the presence and value of parameters would be necessary to support OAuth 2.0 - as both "Resource Owner Password Credentials Grant" and "Refreshing an Access Token" are defined to be on the /token endpoint, but with different values for the grant_type parameter. 
  • Separate out the output generation from the handler mapping. It's surprisingly common to see frameworks that insist on only one output supported, or on requiring different handlers to produce different outputs. What I'd like is one where you have a handler for a given resource that is written once, and then you can say that you convert the output of this into JSON by doing this, or into XML by doing that. All you then need to do is make sure that the handler produces enough information to support all of the required outputs, and make sure you can write the output mapping routines correctly.
  • Sensible way to handle response headers and status codes. Sometimes you actually want to send back a status code that isn't a 200 - 201 and 204 being obvious candidates here, but all of them make sense. And sometimes you have specific needs to support sending back headers of some kind. These headers are actually more complicated because there are two categories they fall into - general ones or request specific ones. You might decide that you always want to send back an X-Application-Version header containing the version fo the software that's running, but you might only want to specify a Link header that is specific to this one resource. These two use cases probably have two different ways of being supported.
  • Sensible way of supporting error handling. Exceptions make sense here, but this means that there needs to be a way of handling an exception and producing an error document to send to the client. Ideally the way that the output from the exception is handled should be the exact same as how the output from the handler is handled - including status code and header generation as well as the actual content to send back. There are again two different ways that exceptions need to be handled - specific to this request or general across everything.
  • Sensible version management. If you're writing a REST API, then it's a fair assumption that you expect people to use it. If you then make changes to the API, you need to be able to do so in a way that doesn't break existing clients. This means versioning of the API itself. I've seen a number of different ways to achieve this - some better than others in my opinion - but it would be nice to have a way that is pluggable into the framework instead of it enforcing one specific way of doing it. That's probably asking a lot though, so I'd be happy with a sensible strategy in place - something like the Accept-Version header.
  • Sensible support for authentication. There are a number of fairly standard ways to authenticate a REST API these days - OAuth comes to mind here - but not everybody wants to do it that way. The ideal way is to have a pluggable mechanism whereby the request can be processed before the handlers get to it to determine if the request is authenticated, and if so who the user is. This should then automatically fail and not get to the request if the authentication isn't valid, or if the request requires authentication and it isn't present.
I also quite like the idea of a framework that has support - if not built in then pluggable - for things like Swagger, which make documenting and testing your API really nice and simple.

On top of all of this as well, I've noticed a growing trend in the JVM world to write your own server first - this is how things like Play work. I'd much prefer a scenario where you build a WAR file and deploy it to any WAR container as you prefer. 

No comments:

Post a Comment