Middlewares¶
Middlewares are functions that take a handler as their input and produces a handler as output. They are useful to enhance behaviour of handlers.
type Middleware req req' a' a = Handler req' a' -> Handler req a
We already met the queryParam
function in the previous section which is a middleware. Here is possible
implementation for it in pseudo-code:
queryParam :: (KnownSymbol name, FromHttpApiData val)
=> Middleware req (QueryParam name val:req) a a
queryParam handler = Kleisli $ \request -> do
res <- probe @(QueryParam name val) request
either sendErrorResponse (runKleisli handler) res
As you can see, this just uses probe
as mentioned in the previous section in an attempt to prove the presence of
the QueryParam
trait. If successful, we call handler
with that result and if unsuccessful, use sendErrorResponse
to handle it.
Types of Middlewares¶
So what are the kind of things we can do in a middleware?
As seen in the queryParam
example, we can modify the request parameter passed to the inner handler. Such
middlewares are called request middlewares and have this type:
type RequestMiddleware req req' a = Middleware req req' a a
Similarly, we have response middlewares which modify the responses sent from the inner handler.
type ResponseMiddleware req a' a = Middleware req req a' a
Of course, we could have a middleware that modifies both the request and response.