The second section of this blog post contains a description of the major new features in servant-0.5 .

We’re happy to announce the release of servant-0.5 . Quite a lot of exciting changes have happened since the last major release. A lot of things happened under the hood, but there’s also a number of changes on the surface. This will force servant users that want to upgrade to perform some changes to their code. Therefore the following section contains an upgrade guide. We hope, upgrading will go smoothly. At least when you didn’t write your own combinators it should be fairly straightforward.

The content-type list now is invariably used to determine whether to respond – that is, even when you’re returning NoContent you need to specify matching content-types.

Methods returning () do not automatically return 204 anymore. Use GetNoContent (and PostNoContent , etc.) in conjunction with the NoContent type instead:

Post now returns 200. Replace Post with PostCreated if you want to stick to the old behaviour, which was returning a 201.

Instead of EitherT (from either ) we now use ExceptT (from mtl ), which behaves the same, but doesn’t add a dependency. Your handler’s types have to change from e.g. EitherT ServantErr IO MyType to ExceptT ServantErr IO MyType . Throwing an error used to work with e.g. left myError and that now has to be switched to throwE myError . Both ExceptT and throwE reside in Control.Monad.Trans.Except .

Major Changes

Trie-based routing Previously routing was O(n) in the number of routes, as we matched them sequentially (and indeed, bodies would sometimes be deserialized more than once). Andres Löh improved this by transforming the routing into a trie.

Context machinery We had an issue that kept annoying us. Consider a HasServer instance for a combinator that provides a User by looking up the cookie in a database. You have to be able to somehow pass the lookup function – or at least a connection to a database – into that instance. But they must be passed in at run-time, and for fairly involved reasons there was no good way of doing so. We added a new parameter to route that is an HList with configuration data not unlike Spock’s Context . If you are not writing HasServer instances, Context requires no changes to your code for upgrading. If you are, note that the HasServer type class has an extra type parameter. This change should enable a variety of new combinators that were difficult or impossible previously. Note that Context is (for now at least) meant only for the configuration of combinator instances, not for the configuration of handlers (use enter for the latter).

Unifying method combinators Previously each of ‘Get’, ‘Put’, ‘Post’, etc. were entirely separate datatypes. This also meant each interpretation needed to included instances for all of them. The 0.5 release makes them instead type-synonyms, e.g.: type Get contentTypes a = Verb ' GET 200 contentTypes a This makes it easy to change the status code of a success response. To further facilitate that, we now provide a variety of other type synonyms for responses other than 200, for example PostCreated for 201.

Non-memoized request body Prior to Andres Löh’s trie-based routing improvements, we had to keep the request body in memory for more-or-less the duration of the request-response cycle. This was of course far from ideal, but necessary given that we could not tell whether the request might be re-routed to a different endpoint. After the changes, we can now remove it. Note however that certain idioms, such as type API = ReqBody '[ JSON ] Int :> Get '[ JSON ] Int :<|> ReqBody '[ JSON ] String :> Get '[ JSON ] String no longer make sense – a request body that cannot be decoded as an Int will be rejected with a 400, and the second endpoint will not be tried. This accords with the behaviour of more traditional frameworks and, as Edsko de Vries showed in a blog post, no loss of expressivity is entailed by the change. We expect this to enable streaming combinators.

Remove matrix params Matrix params were interacting poorly with the rest of servant , because they necessitate special behaviour. We decided to remove them. If you were relying on them and would like to see them back, please let us know.

Switch from EitherT to ExceptT Along with the rest of the world, we’ve moved to ExceptT , which is in mtl . Updating should consist of just replacing all occurrences of EitherT with ExceptT and all occurrences of left with throwE .

NoContent and status codes Previously we were much too smart about HTTP status codes. In particular, when the type of the response was () , we would return 204 ( No Content ). This was sometimes convenient, but generally more trouble than it was worth – some people wanted 200 codes anyhow, some people pointed out that 205 ( Reset Content ) was also often a sensible response, and moreover, () was too generally-used a type to convey the appropriate semantics. We now have a dedicated NoContent type for that, and the status code is up to you to decide (by default it will continue to be 200). NOTE: additionally, and for many of the same reasons, Post now returns an HTTP 200 on success (rather than 201). Use PostCreated if you would like the old behaviour.

servant-js The javascript codegen story has been considerably improved. Not only is there jquery -based codegen, but also Angular , Axios and vanilla (xhr-based) codegen. freezeboy wrote a separate post going into more details about how all of it works – stay tuned for it. Furthermore, we have extracted common functionality for code-generation into servant-foreign . During this change, we have switched from String to the text -package. So if you were using servant-jquery before and are now switching to servant-js , take into account that we do not use the String datatype anymore.

servant-foreign There has been a proliferation of code-generation libraries for servant . With this in mind, Denis Redozubov wrote servant-foreign is a library purposed to address the common code-generation needs. It derives the term-level endpoints descriptions from the servant typelevel API DSL. Once you have this, it’s easy to implement code-generation for any target language. In the nutshell it allows you to generate http api clients for servant servers and incorporate that into your build/CI process. servant-js and some other libraries use servant-foreign under the hood to achieve this.