git.iko.soy/typeable/servant
on master help sign in
expose client runner as a typeclass with base implementation #798

* defined a typeclass abstracting the execution of a query * provide ClientM-based instances for this typeclass * changed signature of client and clientWithRoute to add proxy for context * updated tests

commit5e2c48b08fd7725dd6ea4bd035c2cf8a22846a83 authorArnaud Bailly <arnaud.oqube@gmail.com> dateSun 3 Sep 2017, 08:49 (9 years ago) parent175c953
4 files changed+126−117
servant-client/servant-client.cabal+1 servant-client/src/Servant/Client.hs+103−96 servant-client/src/Servant/Client/Class.hs+4−3 servant-client/test/Servant/ClientSpec.hs+18−18
servant-client/servant-client.cabal+1
@@ -30,6 +30,7 @@ source-repository head
3030library
3131 exposed-modules:
3232 Servant.Client
33+ Servant.Client.Class
3334 Servant.Client.HttpClient
3435 Servant.Client.Generic
3536 Servant.Client.Experimental.Auth
servant-client/src/Servant/Client.hs+103−96
@@ -1,15 +1,16 @@
1−{-# LANGUAGE AllowAmbiguousTypes #-}
2−{-# LANGUAGE CPP #-}
3−{-# LANGUAGE DataKinds #-}
4−{-# LANGUAGE FlexibleContexts #-}
5−{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE InstanceSigs #-}
7−{-# LANGUAGE OverloadedStrings #-}
8−{-# LANGUAGE PolyKinds #-}
9−{-# LANGUAGE ScopedTypeVariables #-}
10−{-# LANGUAGE TypeFamilies #-}
11−{-# LANGUAGE TypeOperators #-}
12−{-# LANGUAGE UndecidableInstances #-}
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE DataKinds #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE InstanceSigs #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE OverloadedStrings #-}
9+{-# LANGUAGE PolyKinds #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE TypeFamilies #-}
12+{-# LANGUAGE TypeOperators #-}
13+{-# LANGUAGE UndecidableInstances #-}
1314
1415#include "overlapping-compat.h"
1516-- | This module provides 'client' which can automatically generate
@@ -62,15 +63,15 @@ import Servant.Common.Req
6263-- > getAllBooks :: ClientM [Book]
6364-- > postNewBook :: Book -> ClientM Book
6465-- > (getAllBooks :<|> postNewBook) = client myApi
65−client :: HasClient api => Proxy api -> Client m api
66−client p = clientWithRoute p defReq
66+client :: HasClient m api => Proxy m -> Proxy api -> Client m api
67+client pm p = clientWithRoute pm p defReq
6768
6869-- | This class lets us define how each API combinator
6970-- influences the creation of an HTTP request. It's mostly
7071-- an internal class, you can just use 'client'.
71−class HasClient api where
72+class HasClient m api where
7273 type Client (m :: * -> *) (api :: *) :: *
73− clientWithRoute :: Proxy api -> Req -> Client m api
74+ clientWithRoute :: Proxy m -> Proxy api -> Req -> Client m api
7475
7576
7677-- | A client querying function for @a ':<|>' b@ will actually hand you
@@ -86,11 +87,11 @@ class HasClient api where
8687-- > getAllBooks :: ClientM [Book]
8788-- > postNewBook :: Book -> ClientM Book
8889-- > (getAllBooks :<|> postNewBook) = client myApi
89−instance (HasClient a, HasClient b) => HasClient (a :<|> b) where
90+instance (HasClient m a, HasClient m b) => HasClient m (a :<|> b) where
9091 type Client m (a :<|> b) = Client m a :<|> Client m b
91− clientWithRoute Proxy req =
92− clientWithRoute (Proxy :: Proxy a) req :<|>
93− clientWithRoute (Proxy :: Proxy b) req
92+ clientWithRoute pm Proxy req =
93+ clientWithRoute pm (Proxy :: Proxy a) req :<|>
94+ clientWithRoute pm (Proxy :: Proxy b) req
9495
9596-- | Singleton type representing a client for an empty API.
9697data EmptyClient = EmptyClient deriving (Eq, Show, Bounded, Enum)
@@ -105,9 +106,9 @@ data EmptyClient = EmptyClient deriving (Eq, Show, Bounded, Enum)
105106-- >
106107-- > getAllBooks :: ClientM [Book]
107108-- > (getAllBooks :<|> EmptyClient) = client myApi
108−instance HasClient EmptyAPI where
109+instance HasClient m EmptyAPI where
109110 type Client m EmptyAPI = EmptyClient
110− clientWithRoute Proxy _ = EmptyClient
111+ clientWithRoute pm Proxy _ = EmptyClient
111112
112113-- | If you use a 'Capture' in one of your endpoints in your API,
113114-- the corresponding querying function will automatically take
@@ -128,14 +129,14 @@ instance HasClient EmptyAPI where
128129-- > getBook :: Text -> ClientM Book
129130-- > getBook = client myApi
130131-- > -- then you can just use "getBook" to query that endpoint
131−instance (KnownSymbol capture, ToHttpApiData a, HasClient api)
132− => HasClient (Capture capture a :> api) where
132+instance (KnownSymbol capture, ToHttpApiData a, HasClient m api)
133+ => HasClient m (Capture capture a :> api) where
133134
134135 type Client m (Capture capture a :> api) =
135136 a -> Client m api
136137
137− clientWithRoute Proxy req val =
138− clientWithRoute (Proxy :: Proxy api)
138+ clientWithRoute pm Proxy req val =
139+ clientWithRoute pm (Proxy :: Proxy api)
139140 (appendToPath p req)
140141
141142 where p = unpack (toUrlPiece val)
@@ -160,14 +161,14 @@ instance (KnownSymbol capture, ToHttpApiData a, HasClient api)
160161-- > getSourceFile :: [Text] -> ClientM SourceFile
161162-- > getSourceFile = client myApi
162163-- > -- then you can use "getSourceFile" to query that endpoint
163−instance (KnownSymbol capture, ToHttpApiData a, HasClient sublayout)
164− => HasClient (CaptureAll capture a :> sublayout) where
164+instance (KnownSymbol capture, ToHttpApiData a, HasClient m sublayout)
165+ => HasClient m (CaptureAll capture a :> sublayout) where
165166
166167 type Client m (CaptureAll capture a :> sublayout) =
167168 [a] -> Client m sublayout
168169
169− clientWithRoute Proxy req vals =
170− clientWithRoute (Proxy :: Proxy sublayout)
170+ clientWithRoute pm Proxy req vals =
171+ clientWithRoute pm (Proxy :: Proxy sublayout)
171172 (foldl' (flip appendToPath) req ps)
172173
173174 where ps = map (unpack . toUrlPiece) vals
@@ -175,27 +176,31 @@ instance (KnownSymbol capture, ToHttpApiData a, HasClient sublayout)
175176instance OVERLAPPABLE_
176177 -- Note [Non-Empty Content Types]
177178 (RunClient m ct ([H.Header], a), MimeUnrender ct a, ReflectMethod method, cts' ~ (ct ': cts)
178− ) => HasClient (Verb method status cts' a) where
179+ ) => HasClient m (Verb method status cts' a) where
179180 type Client m (Verb method status cts' a) = m a
180− clientWithRoute Proxy req = do
181− snd <$> runRequest (Proxy :: Proxy ct) method req
181+ clientWithRoute pm Proxy req = do
182+ (_hdrs, a) :: ([H.Header], a) <- runRequest (Proxy :: Proxy ct) method req
183+ return a
182184 where method = reflectMethod (Proxy :: Proxy method)
183185
184186instance OVERLAPPING_
185− (RunClient m NoContent [H.Header], ReflectMethod method) => HasClient (Verb method status cts NoContent) where
187+ ( RunClient m NoContent [HTTP.Header]
188+ , ReflectMethod method) => HasClient m (Verb method status cts NoContent) where
186189 type Client m (Verb method status cts NoContent)
187190 = m NoContent
188− clientWithRoute Proxy req = do
189− runRequest (Proxy :: Proxy NoContent) method req >> return NoContent
191+ clientWithRoute pm Proxy req = do
192+ _hdrs :: [H.Header] <- runRequest (Proxy :: Proxy NoContent) method req
193+ return NoContent
190194 where method = reflectMethod (Proxy :: Proxy method)
191195
192196instance OVERLAPPING_
193197 -- Note [Non-Empty Content Types]
194− ( RunClient m ct ([H.Header], a), MimeUnrender ct a, BuildHeadersTo ls, ReflectMethod method, cts' ~ (ct ': cts)
195− ) => HasClient (Verb method status cts' (Headers ls a)) where
198+ ( RunClient m ct ([H.Header], a)
199+ , MimeUnrender ct a, BuildHeadersTo ls, ReflectMethod method, cts' ~ (ct ': cts)
200+ ) => HasClient m (Verb method status cts' (Headers ls a)) where
196201 type Client m (Verb method status cts' (Headers ls a))
197202 = m (Headers ls a)
198− clientWithRoute Proxy req = do
203+ clientWithRoute pm Proxy req = do
199204 let method = reflectMethod (Proxy :: Proxy method)
200205 (hdrs, resp) <- runRequest (Proxy :: Proxy ct) method req
201206 return $ Headers { getResponse = resp
@@ -203,13 +208,14 @@ instance OVERLAPPING_
203208 }
204209
205210instance OVERLAPPING_
206− ( RunClient m NoContent [H.Header], BuildHeadersTo ls, ReflectMethod method
207− ) => HasClient (Verb method status cts (Headers ls NoContent)) where
211+ ( RunClient m NoContent [H.Header]
212+ , BuildHeadersTo ls, ReflectMethod method
213+ ) => HasClient m (Verb method status cts (Headers ls NoContent)) where
208214 type Client m (Verb method status cts (Headers ls NoContent))
209215 = m (Headers ls NoContent)
210− clientWithRoute Proxy req = do
216+ clientWithRoute pm Proxy req = do
211217 let method = reflectMethod (Proxy :: Proxy method)
212− hdrs <- runRequest method req
218+ hdrs <- runRequest (Proxy :: Proxy NoContent) method req
213219 return $ Headers { getResponse = NoContent
214220 , getHeadersHList = buildHeadersTo hdrs
215221 }
@@ -240,14 +246,14 @@ instance OVERLAPPING_
240246-- > viewReferer = client myApi
241247-- > -- then you can just use "viewRefer" to query that endpoint
242248-- > -- specifying Nothing or e.g Just "http://haskell.org/" as arguments
243−instance (KnownSymbol sym, ToHttpApiData a, HasClient api)
244− => HasClient (Header sym a :> api) where
249+instance (KnownSymbol sym, ToHttpApiData a, HasClient m api)
250+ => HasClient m (Header sym a :> api) where
245251
246252 type Client m (Header sym a :> api) =
247253 Maybe a -> Client m api
248254
249− clientWithRoute Proxy req mval =
250− clientWithRoute (Proxy :: Proxy api)
255+ clientWithRoute pm Proxy req mval =
256+ clientWithRoute pm (Proxy :: Proxy api)
251257 (maybe req
252258 (\value -> Servant.Common.Req.addHeader hname value req)
253259 mval
@@ -257,26 +263,26 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient api)
257263
258264-- | Using a 'HttpVersion' combinator in your API doesn't affect the client
259265-- functions.
260−instance HasClient api
261− => HasClient (HttpVersion :> api) where
266+instance HasClient m api
267+ => HasClient m (HttpVersion :> api) where
262268
263269 type Client m (HttpVersion :> api) =
264270 Client m api
265271
266− clientWithRoute Proxy =
267− clientWithRoute (Proxy :: Proxy api)
272+ clientWithRoute pm Proxy =
273+ clientWithRoute pm (Proxy :: Proxy api)
268274
269275-- | Ignore @'Summary'@ in client functions.
270−instance HasClient api => HasClient (Summary desc :> api) where
276+instance HasClient m api => HasClient m (Summary desc :> api) where
271277 type Client m (Summary desc :> api) = Client m api
272278
273− clientWithRoute _ = clientWithRoute (Proxy :: Proxy api)
279+ clientWithRoute pm _ = clientWithRoute pm (Proxy :: Proxy api)
274280
275281-- | Ignore @'Description'@ in client functions.
276−instance HasClient api => HasClient (Description desc :> api) where
282+instance HasClient m api => HasClient m (Description desc :> api) where
277283 type Client m (Description desc :> api) = Client m api
278284
279− clientWithRoute _ = clientWithRoute (Proxy :: Proxy api)
285+ clientWithRoute pm _ = clientWithRoute pm (Proxy :: Proxy api)
280286
281287-- | If you use a 'QueryParam' in one of your endpoints in your API,
282288-- the corresponding querying function will automatically take
@@ -303,15 +309,15 @@ instance HasClient api => HasClient (Description desc :> api) where
303309-- > -- then you can just use "getBooksBy" to query that endpoint.
304310-- > -- 'getBooksBy Nothing' for all books
305311-- > -- 'getBooksBy (Just "Isaac Asimov")' to get all books by Isaac Asimov
306−instance (KnownSymbol sym, ToHttpApiData a, HasClient api)
307− => HasClient (QueryParam sym a :> api) where
312+instance (KnownSymbol sym, ToHttpApiData a, HasClient m api)
313+ => HasClient m (QueryParam sym a :> api) where
308314
309315 type Client m (QueryParam sym a :> api) =
310316 Maybe a -> Client m api
311317
312318 -- if mparam = Nothing, we don't add it to the query string
313− clientWithRoute Proxy req mparam =
314− clientWithRoute (Proxy :: Proxy api)
319+ clientWithRoute pm Proxy req mparam =
320+ clientWithRoute pm (Proxy :: Proxy api)
315321 (maybe req
316322 (flip (appendToQueryString pname) req . Just)
317323 mparamText
@@ -348,14 +354,14 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient api)
348354-- > -- 'getBooksBy []' for all books
349355-- > -- 'getBooksBy ["Isaac Asimov", "Robert A. Heinlein"]'
350356-- > -- to get all books by Asimov and Heinlein
351−instance (KnownSymbol sym, ToHttpApiData a, HasClient api)
352− => HasClient (QueryParams sym a :> api) where
357+instance (KnownSymbol sym, ToHttpApiData a, HasClient m api)
358+ => HasClient m (QueryParams sym a :> api) where
353359
354360 type Client m (QueryParams sym a :> api) =
355361 [a] -> Client m api
356362
357− clientWithRoute Proxy req paramlist =
358− clientWithRoute (Proxy :: Proxy api)
363+ clientWithRoute pm Proxy req paramlist =
364+ clientWithRoute pm (Proxy :: Proxy api)
359365 (foldl' (\ req' -> maybe req' (flip (appendToQueryString pname) req' . Just))
360366 req
361367 paramlist'
@@ -386,14 +392,14 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient api)
386392-- > -- then you can just use "getBooks" to query that endpoint.
387393-- > -- 'getBooksBy False' for all books
388394-- > -- 'getBooksBy True' to only get _already published_ books
389−instance (KnownSymbol sym, HasClient api)
390− => HasClient (QueryFlag sym :> api) where
395+instance (KnownSymbol sym, HasClient m api)
396+ => HasClient m (QueryFlag sym :> api) where
391397
392398 type Client m (QueryFlag sym :> api) =
393399 Bool -> Client m api
394400
395− clientWithRoute Proxy req flag =
396− clientWithRoute (Proxy :: Proxy api)
401+ clientWithRoute pm Proxy req flag =
402+ clientWithRoute pm (Proxy :: Proxy api)
397403 (if flag
398404 then appendToQueryString paramname Nothing req
399405 else req
@@ -404,12 +410,13 @@ instance (KnownSymbol sym, HasClient api)
404410
405411-- | Pick a 'Method' and specify where the server you want to query is. You get
406412-- back the full `Response`.
407−instance HasClient Raw where
413+instance (RunClient m NoContent (Int, ByteString, MediaType, [HTTP.Header], Response ByteString))
414+ => HasClient m Raw where
408415 type Client m Raw
409416 = H.Method -> m (Int, ByteString, MediaType, [HTTP.Header], Response ByteString)
410417
411− clientWithRoute :: Proxy Raw -> Req -> Client Raw
412− clientWithRoute Proxy req httpMethod = do
418+ clientWithRoute :: Proxy m -> Proxy Raw -> Req -> Client m Raw
419+ clientWithRoute pm Proxy req httpMethod = do
413420 runRequest (Proxy :: Proxy NoContent) httpMethod req
414421
415422-- | If you use a 'ReqBody' in one of your endpoints in your API,
@@ -430,14 +437,14 @@ instance HasClient Raw where
430437-- > addBook :: Book -> ClientM Book
431438-- > addBook = client myApi
432439-- > -- then you can just use "addBook" to query that endpoint
433−instance (MimeRender ct a, HasClient api)
434− => HasClient (ReqBody (ct ': cts) a :> api) where
440+instance (MimeRender ct a, HasClient m api)
441+ => HasClient m (ReqBody (ct ': cts) a :> api) where
435442
436443 type Client m (ReqBody (ct ': cts) a :> api) =
437444 a -> Client m api
438445
439− clientWithRoute Proxy req body =
440− clientWithRoute (Proxy :: Proxy api)
446+ clientWithRoute pm Proxy req body =
447+ clientWithRoute pm (Proxy :: Proxy api)
441448 (let ctProxy = Proxy :: Proxy ct
442449 in setReqBodyLBS (mimeRender ctProxy body)
443450 -- We use first contentType from the Accept list
@@ -446,54 +453,54 @@ instance (MimeRender ct a, HasClient api)
446453 )
447454
448455-- | Make the querying function append @path@ to the request path.
449−instance (KnownSymbol path, HasClient api) => HasClient (path :> api) where
456+instance (KnownSymbol path, HasClient m api) => HasClient m (path :> api) where
450457 type Client m (path :> api) = Client m api
451458
452− clientWithRoute Proxy req =
453− clientWithRoute (Proxy :: Proxy api)
459+ clientWithRoute pm Proxy req =
460+ clientWithRoute pm (Proxy :: Proxy api)
454461 (appendToPath p req)
455462
456463 where p = symbolVal (Proxy :: Proxy path)
457464
458−instance HasClient api => HasClient (Vault :> api) where
465+instance HasClient m api => HasClient m (Vault :> api) where
459466 type Client m (Vault :> api) = Client m api
460467
461− clientWithRoute Proxy req =
462− clientWithRoute (Proxy :: Proxy api) req
468+ clientWithRoute pm Proxy req =
469+ clientWithRoute pm (Proxy :: Proxy api) req
463470
464−instance HasClient api => HasClient (RemoteHost :> api) where
471+instance HasClient m api => HasClient m (RemoteHost :> api) where
465472 type Client m (RemoteHost :> api) = Client m api
466473
467− clientWithRoute Proxy req =
468− clientWithRoute (Proxy :: Proxy api) req
474+ clientWithRoute pm Proxy req =
475+ clientWithRoute pm (Proxy :: Proxy api) req
469476
470−instance HasClient api => HasClient (IsSecure :> api) where
477+instance HasClient m api => HasClient m (IsSecure :> api) where
471478 type Client m (IsSecure :> api) = Client m api
472479
473− clientWithRoute Proxy req =
474− clientWithRoute (Proxy :: Proxy api) req
480+ clientWithRoute pm Proxy req =
481+ clientWithRoute pm (Proxy :: Proxy api) req
475482
476−instance HasClient subapi =>
477− HasClient (WithNamedContext name context subapi) where
483+instance HasClient m subapi =>
484+ HasClient m (WithNamedContext name context subapi) where
478485
479486 type Client m (WithNamedContext name context subapi) = Client m subapi
480− clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy subapi)
487+ clientWithRoute pm Proxy = clientWithRoute pm (Proxy :: Proxy subapi)
481488
482−instance ( HasClient api
483− ) => HasClient (AuthProtect tag :> api) where
489+instance ( HasClient m api
490+ ) => HasClient m (AuthProtect tag :> api) where
484491 type Client m (AuthProtect tag :> api)
485492 = AuthenticateReq (AuthProtect tag) -> Client m api
486493
487− clientWithRoute Proxy req (AuthenticateReq (val,func)) =
488− clientWithRoute (Proxy :: Proxy api) (func val req)
494+ clientWithRoute pm Proxy req (AuthenticateReq (val,func)) =
495+ clientWithRoute pm (Proxy :: Proxy api) (func val req)
489496
490497-- * Basic Authentication
491498
492−instance HasClient api => HasClient (BasicAuth realm usr :> api) where
499+instance HasClient m api => HasClient m (BasicAuth realm usr :> api) where
493500 type Client m (BasicAuth realm usr :> api) = BasicAuthData -> Client m api
494501
495− clientWithRoute Proxy req val =
496− clientWithRoute (Proxy :: Proxy api) (basicAuthReq val req)
502+ clientWithRoute pm Proxy req val =
503+ clientWithRoute pm (Proxy :: Proxy api) (basicAuthReq val req)
497504
498505
499506{- Note [Non-Empty Content Types]
servant-client/src/Servant/Client/Class.hs+4−3
@@ -10,6 +10,7 @@ import Servant.API
1010import Servant.Common.Req
1111
1212class (Monad m) => RunClient m ct result where
13− runRequest :: MimeUnrender ct result
14− => Proxy ct
15− -> Method -> Req -> m result
13+ runRequest :: Proxy ct
14+ -> Method
15+ -> Req
16+ -> m result
servant-client/test/Servant/ClientSpec.hs+18−18
@@ -63,7 +63,7 @@ import Servant.Server
6363import Servant.Server.Experimental.Auth
6464
6565-- This declaration simply checks that all instances are in place.
66−_ = client comprehensiveAPI
66+_ = client (Proxy :: Proxy ClientM) comprehensiveAPI
6767
6868spec :: Spec
6969spec = describe "Servant.Client" $ do
@@ -147,7 +147,7 @@ getGet
147147 :<|> getMultiple
148148 :<|> getRespHeaders
149149 :<|> getDeleteContentType
150− :<|> EmptyClient = client api
150+ :<|> EmptyClient = client (Proxy :: Proxy ClientM) api
151151
152152server :: Application
153153server = serve api (
@@ -241,7 +241,7 @@ data GenericClient = GenericClient
241241 , mkNestedClient1 :: String -> NestedClient1
242242 } deriving Generic
243243instance SOP.Generic GenericClient
244−instance (Client GenericClientAPI ~ client) => ClientLike client GenericClient
244+instance (Client ClientM GenericClientAPI ~ client) => ClientLike client GenericClient
245245
246246type NestedAPI1
247247 = QueryParam "int" Int :> NestedAPI2
@@ -252,7 +252,7 @@ data NestedClient1 = NestedClient1
252252 , idChar :: Maybe Char -> SCR.ClientM Char
253253 } deriving Generic
254254instance SOP.Generic NestedClient1
255−instance (Client NestedAPI1 ~ client) => ClientLike client NestedClient1
255+instance (Client ClientM NestedAPI1 ~ client) => ClientLike client NestedClient1
256256
257257type NestedAPI2
258258 = "sum" :> Capture "first" Int :> Capture "second" Int :> Get '[JSON] Int
@@ -263,7 +263,7 @@ data NestedClient2 = NestedClient2
263263 , doNothing :: SCR.ClientM ()
264264 } deriving Generic
265265instance SOP.Generic NestedClient2
266−instance (Client NestedAPI2 ~ client) => ClientLike client NestedClient2
266+instance (Client ClientM NestedAPI2 ~ client) => ClientLike client NestedClient2
267267
268268genericClientServer :: Application
269269genericClientServer = serve (Proxy :: Proxy GenericClientAPI) (
@@ -359,7 +359,7 @@ wrappedApiSpec = describe "error status codes" $ do
359359 test (WrappedApi api, desc) =
360360 it desc $ bracket (startWaiApp $ serveW api) endWaiApp $ \(_, baseUrl) -> do
361361 let getResponse :: SCR.ClientM ()
362− getResponse = client api
362+ getResponse = client (Proxy :: Proxy ClientM) api
363363 Left FailureResponse{..} <- runClientM getResponse (ClientEnv manager baseUrl)
364364 responseStatus `shouldBe` (HTTP.Status 500 "error message")
365365 in mapM_ test $
@@ -374,35 +374,35 @@ failSpec = beforeAll (startWaiApp failServer) $ afterAll endWaiApp $ do
374374
375375 context "client returns errors appropriately" $ do
376376 it "reports FailureResponse" $ \(_, baseUrl) -> do
377− let (_ :<|> getDeleteEmpty :<|> _) = client api
377+ let (_ :<|> getDeleteEmpty :<|> _) = client (Proxy :: Proxy ClientM) api
378378 Left res <- runClientM getDeleteEmpty (ClientEnv manager baseUrl)
379379 case res of
380380 FailureResponse _ (HTTP.Status 404 "Not Found") _ _ -> return ()
381381 _ -> fail $ "expected 404 response, but got " <> show res
382382
383383 it "reports DecodeFailure" $ \(_, baseUrl) -> do
384− let (_ :<|> _ :<|> getCapture :<|> _) = client api
384+ let (_ :<|> _ :<|> getCapture :<|> _) = client (Proxy :: Proxy ClientM) api
385385 Left res <- runClientM (getCapture "foo") (ClientEnv manager baseUrl)
386386 case res of
387387 DecodeFailure _ ("application/json") _ -> return ()
388388 _ -> fail $ "expected DecodeFailure, but got " <> show res
389389
390390 it "reports ConnectionError" $ \_ -> do
391− let (getGetWrongHost :<|> _) = client api
391+ let (getGetWrongHost :<|> _) = client (Proxy :: Proxy ClientM) api
392392 Left res <- runClientM getGetWrongHost (ClientEnv manager (BaseUrl Http "127.0.0.1" 19872 ""))
393393 case res of
394394 ConnectionError _ -> return ()
395395 _ -> fail $ "expected ConnectionError, but got " <> show res
396396
397397 it "reports UnsupportedContentType" $ \(_, baseUrl) -> do
398− let (getGet :<|> _ ) = client api
398+ let (getGet :<|> _ ) = client (Proxy :: Proxy ClientM) api
399399 Left res <- runClientM getGet (ClientEnv manager baseUrl)
400400 case res of
401401 UnsupportedContentType ("application/octet-stream") _ -> return ()
402402 _ -> fail $ "expected UnsupportedContentType, but got " <> show res
403403
404404 it "reports InvalidContentTypeHeader" $ \(_, baseUrl) -> do
405− let (_ :<|> _ :<|> _ :<|> _ :<|> getBody :<|> _) = client api
405+ let (_ :<|> _ :<|> _ :<|> _ :<|> getBody :<|> _) = client (Proxy :: Proxy ClientM) api
406406 Left res <- runClientM (getBody alice) (ClientEnv manager baseUrl)
407407 case res of
408408 InvalidContentTypeHeader "fooooo" _ -> return ()
@@ -410,7 +410,7 @@ failSpec = beforeAll (startWaiApp failServer) $ afterAll endWaiApp $ do
410410
411411data WrappedApi where
412412 WrappedApi :: (HasServer (api :: *) '[], Server api ~ Handler a,
413− HasClient api, Client api ~ SCR.ClientM ()) =>
413+ HasClient ClientM api, Client ClientM api ~ SCR.ClientM ()) =>
414414 Proxy api -> WrappedApi
415415
416416basicAuthSpec :: Spec
@@ -418,14 +418,14 @@ basicAuthSpec = beforeAll (startWaiApp basicAuthServer) $ afterAll endWaiApp $ d
418418 context "Authentication works when requests are properly authenticated" $ do
419419
420420 it "Authenticates a BasicAuth protected server appropriately" $ \(_,baseUrl) -> do
421− let getBasic = client basicAuthAPI
421+ let getBasic = client (Proxy :: Proxy ClientM) basicAuthAPI
422422 let basicAuthData = BasicAuthData "servant" "server"
423423 (left show <$> runClientM (getBasic basicAuthData) (ClientEnv manager baseUrl)) `shouldReturn` Right alice
424424
425425 context "Authentication is rejected when requests are not authenticated properly" $ do
426426
427427 it "Authenticates a BasicAuth protected server appropriately" $ \(_,baseUrl) -> do
428− let getBasic = client basicAuthAPI
428+ let getBasic = client (Proxy :: Proxy ClientM) basicAuthAPI
429429 let basicAuthData = BasicAuthData "not" "password"
430430 Left FailureResponse{..} <- runClientM (getBasic basicAuthData) (ClientEnv manager baseUrl)
431431 responseStatus `shouldBe` HTTP.Status 403 "Forbidden"
@@ -435,14 +435,14 @@ genAuthSpec = beforeAll (startWaiApp genAuthServer) $ afterAll endWaiApp $ do
435435 context "Authentication works when requests are properly authenticated" $ do
436436
437437 it "Authenticates a AuthProtect protected server appropriately" $ \(_, baseUrl) -> do
438− let getProtected = client genAuthAPI
438+ let getProtected = client (Proxy :: Proxy ClientM) genAuthAPI
439439 let authRequest = mkAuthenticateReq () (\_ req -> SCR.addHeader "AuthHeader" ("cool" :: String) req)
440440 (left show <$> runClientM (getProtected authRequest) (ClientEnv manager baseUrl)) `shouldReturn` Right alice
441441
442442 context "Authentication is rejected when requests are not authenticated properly" $ do
443443
444444 it "Authenticates a AuthProtect protected server appropriately" $ \(_, baseUrl) -> do
445− let getProtected = client genAuthAPI
445+ let getProtected = client (Proxy :: Proxy ClientM) genAuthAPI
446446 let authRequest = mkAuthenticateReq () (\_ req -> SCR.addHeader "Wrong" ("header" :: String) req)
447447 Left FailureResponse{..} <- runClientM (getProtected authRequest) (ClientEnv manager baseUrl)
448448 responseStatus `shouldBe` (HTTP.Status 401 "Unauthorized")
@@ -451,11 +451,11 @@ genericClientSpec :: Spec
451451genericClientSpec = beforeAll (startWaiApp genericClientServer) $ afterAll endWaiApp $ do
452452 describe "Servant.Client.Generic" $ do
453453
454− let GenericClient{..} = mkClient (client (Proxy :: Proxy GenericClientAPI))
454+ let GenericClient{..} = mkClient (client (Proxy :: Proxy ClientM) (Proxy :: Proxy GenericClientAPI))
455455 NestedClient1{..} = mkNestedClient1 "example"
456456 NestedClient2{..} = mkNestedClient2 (Just 42)
457457
458− it "works for top-level client function" $ \(_, baseUrl) -> do
458+ it "works for top-level client (Proxy :: Proxy ClientM) function" $ \(_, baseUrl) -> do
459459 (left show <$> (runClientM (getSqr (Just 5)) (ClientEnv manager baseUrl))) `shouldReturn` Right 25
460460
461461 it "works for nested clients" $ \(_, baseUrl) -> do