@@ -72,16 +72,27 @@ import qualified Network.HTTP.Client as Client
72import qualified Servant.Types.SourceT as S
72import qualified Servant.Types.SourceT as S
74-- | The environment in which a request is run.
74-- | The environment in which a request is run.
75+-- The 'baseUrl' and 'makeClientRequest' function are used to create a @http-client@ request.
76+-- Cookies are then added to that request if a 'CookieJar' is set on the environment.
77+-- Finally the request is executed with the 'manager'.
78+-- The 'makeClientRequest' function can be used to modify the request to execute and set values which
79+-- are not specified on a @servant@ 'Request' like 'responseTimeout' or 'redirectCount'
75data ClientEnv
80data ClientEnv
76 = ClientEnv
81 = ClientEnv
77 { manager :: Client.Manager
82 { manager :: Client.Manager
78 , baseUrl :: BaseUrl
83 , baseUrl :: BaseUrl
79 , cookieJar :: Maybe (TVar Client.CookieJar)
84 , cookieJar :: Maybe (TVar Client.CookieJar)
85+ , makeClientRequest :: BaseUrl -> Request -> Client.Request
86+ -- ^ this function can be used to customize the creation of @http-client@ requests from @servant@ requests. Default value: 'defaultMakeClientRequest'
88+ -- 1. 'makeClientRequest' exists to allow overriding operational semantics e.g. 'responseTimeout' per request,
89+ -- If you need global modifications, you should use 'managerModifyRequest'
90+ -- 2. the 'cookieJar', if defined, is being applied after 'makeClientRequest' is called.
82-- | 'ClientEnv' smart constructor.
93-- | 'ClientEnv' smart constructor.
83mkClientEnv :: Client.Manager -> BaseUrl -> ClientEnv
94mkClientEnv :: Client.Manager -> BaseUrl -> ClientEnv
84−mkClientEnv mgr burl = ClientEnv mgr burl Nothing
95+mkClientEnv mgr burl = ClientEnv mgr burl Nothing defaultMakeClientRequest
86-- | Generates a set of client functions for an API.
97-- | Generates a set of client functions for an API.
@@ -152,8 +163,8 @@ runClientM cm env = runExceptT $ flip runReaderT env $ unClientM cm
153performRequest :: Request -> ClientM Response
164performRequest :: Request -> ClientM Response
154performRequest req = do
165performRequest req = do
155− ClientEnv m burl cookieJar' <- ask
166+ ClientEnv m burl cookieJar' createClientRequest <- ask
156− let clientRequest = requestToClientRequest burl req
167+ let clientRequest = createClientRequest burl req
157 request <- case cookieJar' of
168 request <- case cookieJar' of
158 Nothing -> pure clientRequest
169 Nothing -> pure clientRequest
159 Just cj -> liftIO $ do
170 Just cj -> liftIO $ do
@@ -162,7 +173,7 @@ performRequest req = do
162 oldCookieJar <- readTVar cj
173 oldCookieJar <- readTVar cj
163 let (newRequest, newCookieJar) =
174 let (newRequest, newCookieJar) =
164 Client.insertCookiesIntoRequest
175 Client.insertCookiesIntoRequest
165− (requestToClientRequest burl req)
176+ clientRequest
166 oldCookieJar
177 oldCookieJar
168 writeTVar cj newCookieJar
179 writeTVar cj newCookieJar
@@ -215,8 +226,11 @@ clientResponseToResponse f r = Response
215 , responseHttpVersion = Client.responseVersion r
226 , responseHttpVersion = Client.responseVersion r
229+-- | Create a @http-client@ 'Client.Request' from a @servant@ 'Request'
230+-- The 'Client.host', 'Client.path' and 'Client.port' fields are extracted from the 'BaseUrl'
231+-- otherwise the body, headers and query string are derived from the @servant@ 'Request'
218−requestToClientRequest :: BaseUrl -> Request -> Client.Request
232+defaultMakeClientRequest :: BaseUrl -> Request -> Client.Request
219−requestToClientRequest burl r = Client.defaultRequest
233+defaultMakeClientRequest burl r = Client.defaultRequest
220 { Client.method = requestMethod r
234 { Client.method = requestMethod r
221 , Client.host = fromString $ baseUrlHost burl
235 , Client.host = fromString $ baseUrlHost burl
222 , Client.port = baseUrlPort burl
236 , Client.port = baseUrlPort burl