@@ -0,0 +1,64 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE UndecidableInstances #-}
4+module Web.Tracking.Servant.Types where
8+import Control.Monad ((<=<))
9+import Control.Monad.IO.Class
10+import Data.ByteString (ByteString)
16+import Servant.Server.Internal
18+-- | Types to use in you API description
21+-- | Same as above, except no argument is passed to a handler.
24+newtype ReqtrackingHandler r o = ReqtrackingHandler { unReqtrackingHandler :: r -> Handler o
27+mkReqtrackingHandler :: (r -> Handler o) -> ReqtrackingHandler r o
28+mkReqtrackingHandler = ReqtrackingHandler
30+instance forall (api :: Type) context.
31+ ( HasServer api context
32+ , HasContextEntry context (ReqtrackingHandler Request (Maybe ReqtrackInfo))
33+ ) => HasServer (RequestTracking :> api) context where
34+ type ServerT (RequestTracking :> api) m = Maybe ReqtrackInfo -> ServerT api m
36+ hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s
38+ route _ context subserver = route (Proxy :: Proxy api) context (subserver `addHeaderCheck` withRequest trackingCheck)
39+ where trackingCheck :: Request -> DelayedIO (Maybe ReqtrackInfo)
40+ trackingCheck = either delayedFailFatal return <=< liftIO . runHandler . trackingHandler
41+ trackingHandler :: Request -> Handler (Maybe ReqtrackInfo)
42+ trackingHandler = let ReqtrackingHandler h = getContextEntry context
45+instance forall (api :: Type) context.
46+ ( HasServer api context
47+ , HasContextEntry context (ReqtrackingHandler Request (Maybe ReqtrackInfo))
48+ ) => HasServer (RequestTracking_ :> api) context where
49+ type ServerT (RequestTracking_ :> api) m = ServerT api m
51+ hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt s
53+ route _ context subserver = route (Proxy :: Proxy api) context (fmap const subserver `addHeaderCheck` withRequest trackingCheck)
54+ where trackingCheck :: Request -> DelayedIO ()
55+ trackingCheck = either delayedFailFatal (const $ return ())<=< liftIO . runHandler . trackingHandler
56+ trackingHandler :: Request -> Handler (Maybe ReqtrackInfo)
57+ trackingHandler = let ReqtrackingHandler h = getContextEntry context
61+type ReqtrackHeaders = '[ Header RequestIdHdr ByteString
62+ , Header RequestLevelHdr Word
63+ , Header RequestSourceHdr ByteString