| CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 422
Description
I've been stuck on this for a while and would appreciate some help/someone to enshrine how to do this axiomatically in Servant. All I'm trying to do is add a DB connection that goes along with the request. In trying to avoid global state, there are only a few places such a resource can go, namely:
- Vault (literally on the request)
- App Context (inside servant app machinery)
Making a warp middleware to do (1) was pretty easy and intuitive. Then came the problem of storing the lookup key to the vault (which seems to require (2) ). At this point I tried to do it axiomatically within servant, and do (2) outright -- creating a combinator that supplies the a "backend".
So far what I have is:
-- Servant combinator for including the database handler in subsequent requests
data WithBackend a
deriving Typeable
instance (HasContextEntry context a, Backend a, HasServer api context) => HasServer (WithBackend a :> api) context where
type ServerT (WithBackend a :> api) m = ServerT api m
route Proxy ctx subserver = route api ctx subserver
where
api = (Proxy :: Proxy api)This example is a combinator that doesn't do anything (just uses the sub server) -- however, when I change the type ServerT to a -> ServerT api m, the types stop matching up and it's unclear what to do next. I could modify the context and use the modified context, but I was hoping to be able to make my handlers of type SqliteBackend -> Handler x for example, with this combinator being the thing to add the backend.
I haven't been able to find any explanation of how to do this, everyone handwaves it and says it would be easy, but I'm finding it very difficult. I found the documentation easy to follow but an explanation of HasServer and how to roll your own NON-AUTH combinators might make it perfect.