Using a configuration in Scotty

At work we’re only now getting around to put correlation IDs into use. We write most our code in Clojure but since I’d really like to use more Haskell at work I thought I’d dive into Scotty and see how to deal with logging and then especially how to get correlation IDs into the logs.

The types

For configuration it decided to use the reader monad inside ActionT from Scotty. Enter Chell:

In order to run it I wrote a function corresponding to scotty:

Correlation ID

To deal with the correlation ID each incoming request should be checked for the HTTP header X-Correlation-Id and if present it should be used during logging. If no such header is present then a new correlation ID should be created. Since it’s per request it feels natural to create a WAI middleware for this.

The easiest way I could come up with was to push the correlation ID into the request’s headers before it’s passed on:

It also turns out to be useful to have both a default correlation ID and a function for pulling it out of the headers:

Getting the correlation ID into the configuration

Since the correlation ID should be picked out of the request on handling of every request it’s useful to have it the configuration when running the ChellActionM actions. However, since the correlation ID isn’t available when running the reader (the call to runReaderT in chell) something else is called for. When looking around I found local (and later I was pointed to the more general withReaderT) but it doesn’t have a suitable type. After some help on Twitter I arrived at withConfig which allows me to run an action in a modified configuration:

Making it handy to use

Armed with this I can put together some functions to replace Scotty’s get, post, etc. With a configuration type like this:

The modified get looks like this (Scotty’s original is S.get)

With this in place I can use the simpler ReaderT Config IO for inner functions that need to log.

⟸ QuickCheck on a REST API Picking up new rows in a DB ⟹
Leave a comment