@@ -17,17 +17,55 @@ import Servant.Client.Core
1717import Servant.Server
1818import Servant.Server.Internal
1919
20−-- | Types to use in you API description
20+-- | Combinator for your Servant API description. Prepend it to your API for greater enjoyment!
21+-- Example:
22+--
23+-- @
24+-- type MyAPI = RequestTracking :> "ping" :> Get '[JSON] Text
25+-- @
26+--
27+-- In addition to the API combinator, you also need to create a context handler that will
28+-- handler the tracking data (see 'ReqtrackInfo') and produce desired output, which in turn
29+-- will be passed to your API handlers.
30+-- The type of values passed to API handlers is controlled by @type instance TrackingData RequestTracking@,
31+-- which isn't set by default.
32+-- The server code should look something like this:
33+--
34+-- @
35+-- data TrackingArg = ...
36+--
37+-- type instance TrackingData RequestTracking = TrackingArg
38+--
39+-- trackingHandler :: ReqtrackingHandler (Maybe ReqtrackInfo) TrackingArg
40+-- trackingHandler = mkReqtrackingHandler $ \mrti ->
41+-- case mrti of
42+-- Just rti -> ... -- Do something with ReqtrackInfo, return TrackingArg
43+-- Nothing -> ...
44+--
45+-- @
2146data RequestTracking
2247
48+-- | See 'RequestTracking'
2349type family TrackingData a
2450
2551-- | Same as above, except no argument is passed to a handler.
2652data RequestTracking_
2753
28−newtype ReqtrackingHandler r o = ReqtrackingHandler { unReqtrackingHandler :: r -> Handler o
54+-- | Servant context handler used for processing 'ReqtrackInfo' before passing the result to endpoint handlers.
55+-- Use 'mkReqtrackingHandler' in your code instead of the constructor.
56+newtype ReqtrackingHandler r o = ReqtrackingHandler { runReqtrackingHandler :: r -> Handler o
2957 } deriving (Functor)
3058
59+instance Applicative (ReqtrackingHandler r) where
60+ pure x = ReqtrackingHandler $ \_ -> pure x
61+ f <*> v = ReqtrackingHandler $ \r -> runReqtrackingHandler f r <*> runReqtrackingHandler v r
62+
63+instance Monad (ReqtrackingHandler r) where
64+ return = pure
65+ f >>= g = ReqtrackingHandler $ \r -> do a <- runReqtrackingHandler f r
66+ runReqtrackingHandler (g a) r
67+
68+-- | Smart constructor to create 'ReqtrackingHandler'.
3169mkReqtrackingHandler :: (Maybe ReqtrackInfo -> Handler o) -> ReqtrackingHandler (Maybe ReqtrackInfo) o
3270mkReqtrackingHandler = ReqtrackingHandler
3371
@@ -78,6 +116,7 @@ instance HasClient m api => HasClient m (RequestTracking_ :> api) where
78116 hoistClientMonad pm Proxy f cl = hoistClientMonad pm (Proxy :: Proxy api) f cl
79117
80118
119+-- | Headers list to use with 'Headers'. Currently unused.
81120type ReqtrackHeaders = '[ Header RequestIdHdr ByteString
82121 , Header RequestLevelHdr Word
83122 , Header RequestSourceHdr ByteString