@@ -2,6 +2,7 @@
2{-# LANGUAGE InstanceSigs #-}
2{-# LANGUAGE InstanceSigs #-}
3{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE TypeFamilies #-}
4{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE TypeOperators #-}
5+{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE OverlappingInstances #-}
8{-# LANGUAGE OverlappingInstances #-}
@@ -12,6 +13,7 @@
12module Servant.Client
13module Servant.Client
14 , HasClient(..)
15 , HasClient(..)
15 , ServantError(..)
17 , ServantError(..)
16 , module Servant.Common.BaseUrl
18 , module Servant.Common.BaseUrl
@@ -45,15 +47,17 @@ import Servant.Common.Req
45-- > getAllBooks :: BaseUrl -> EitherT String IO [Book]
47-- > getAllBooks :: BaseUrl -> EitherT String IO [Book]
46-- > postNewBook :: Book -> BaseUrl -> EitherT String IO Book
48-- > postNewBook :: Book -> BaseUrl -> EitherT String IO Book
47-- > (getAllBooks :<|> postNewBook) = client myApi
49-- > (getAllBooks :<|> postNewBook) = client myApi
48−client :: HasClient layout => Proxy layout -> Client layout
50+client :: HasClient (Canonicalize layout) => Proxy layout -> Client layout
49−client p = clientWithRoute p defReq
51+client p = clientWithRoute (canonicalize p) defReq
51-- | This class lets us define how each API combinator
53-- | This class lets us define how each API combinator
52-- influences the creation of an HTTP request. It's mostly
54-- influences the creation of an HTTP request. It's mostly
53-- an internal class, you can just use 'client'.
55-- an internal class, you can just use 'client'.
54class HasClient layout where
56class HasClient layout where
55− type Client layout :: *
57+ type Client' layout :: *
56− clientWithRoute :: Proxy layout -> Req -> Client layout
58+ clientWithRoute :: Proxy layout -> Req -> Client' layout
60+type Client layout = Client' (Canonicalize layout)
58-- | A client querying function for @a ':<|>' b@ will actually hand you
62-- | A client querying function for @a ':<|>' b@ will actually hand you
59-- one function for querying @a@ and another one for querying @b@,
63-- one function for querying @a@ and another one for querying @b@,
@@ -69,7 +73,7 @@ class HasClient layout where
69-- > postNewBook :: Book -> BaseUrl -> EitherT String IO Book
73-- > postNewBook :: Book -> BaseUrl -> EitherT String IO Book
70-- > (getAllBooks :<|> postNewBook) = client myApi
74-- > (getAllBooks :<|> postNewBook) = client myApi
71instance (HasClient a, HasClient b) => HasClient (a :<|> b) where
75instance (HasClient a, HasClient b) => HasClient (a :<|> b) where
72− type Client (a :<|> b) = Client a :<|> Client b
76+ type Client' (a :<|> b) = Client' a :<|> Client' b
73 clientWithRoute Proxy req =
77 clientWithRoute Proxy req =
74 clientWithRoute (Proxy :: Proxy a) req :<|>
78 clientWithRoute (Proxy :: Proxy a) req :<|>
75 clientWithRoute (Proxy :: Proxy b) req
79 clientWithRoute (Proxy :: Proxy b) req
@@ -96,8 +100,8 @@ instance (HasClient a, HasClient b) => HasClient (a :<|> b) where
96instance (KnownSymbol capture, ToText a, HasClient sublayout)
100instance (KnownSymbol capture, ToText a, HasClient sublayout)
97 => HasClient (Capture capture a :> sublayout) where
101 => HasClient (Capture capture a :> sublayout) where
99− type Client (Capture capture a :> sublayout) =
103+ type Client' (Capture capture a :> sublayout) =
100− a -> Client sublayout
104+ a -> Client' sublayout
102 clientWithRoute Proxy req val =
106 clientWithRoute Proxy req val =
103 clientWithRoute (Proxy :: Proxy sublayout) $
107 clientWithRoute (Proxy :: Proxy sublayout) $
@@ -110,7 +114,7 @@ instance (KnownSymbol capture, ToText a, HasClient sublayout)
110-- will just require an argument that specifies the scheme, host
114-- will just require an argument that specifies the scheme, host
111-- and port to send the request to.
115-- and port to send the request to.
112instance HasClient Delete where
116instance HasClient Delete where
113− type Client Delete = BaseUrl -> EitherT ServantError IO ()
117+ type Client' Delete = BaseUrl -> EitherT ServantError IO ()
115 clientWithRoute Proxy req host =
119 clientWithRoute Proxy req host =
116 void $ performRequest H.methodDelete req (`elem` [200, 202, 204]) host
120 void $ performRequest H.methodDelete req (`elem` [200, 202, 204]) host
@@ -120,14 +124,14 @@ instance HasClient Delete where
120-- will just require an argument that specifies the scheme, host
124-- will just require an argument that specifies the scheme, host
121-- and port to send the request to.
125-- and port to send the request to.
122instance (MimeUnrender ct result) => HasClient (Get (ct ': cts) result) where
126instance (MimeUnrender ct result) => HasClient (Get (ct ': cts) result) where
123− type Client (Get (ct ': cts) result) = BaseUrl -> EitherT ServantError IO result
127+ type Client' (Get (ct ': cts) result) = BaseUrl -> EitherT ServantError IO result
124 clientWithRoute Proxy req host =
128 clientWithRoute Proxy req host =
125 performRequestCT (Proxy :: Proxy ct) H.methodGet req [200, 203] host
129 performRequestCT (Proxy :: Proxy ct) H.methodGet req [200, 203] host
127-- | If you have a 'Get xs ()' endpoint, the client expects a 204 No Content
131-- | If you have a 'Get xs ()' endpoint, the client expects a 204 No Content
128-- HTTP header.
132-- HTTP header.
129instance HasClient (Get (ct ': cts) ()) where
133instance HasClient (Get (ct ': cts) ()) where
130− type Client (Get (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
134+ type Client' (Get (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
131 clientWithRoute Proxy req host =
135 clientWithRoute Proxy req host =
132 performRequestNoBody H.methodGet req [204] host
136 performRequestNoBody H.methodGet req [204] host
@@ -159,12 +163,12 @@ instance HasClient (Get (ct ': cts) ()) where
159instance (KnownSymbol sym, ToText a, HasClient sublayout)
163instance (KnownSymbol sym, ToText a, HasClient sublayout)
160 => HasClient (Header sym a :> sublayout) where
164 => HasClient (Header sym a :> sublayout) where
162− type Client (Header sym a :> sublayout) =
166+ type Client' (Header sym a :> sublayout) =
163− Maybe a -> Client sublayout
167+ Maybe a -> Client' sublayout
165 clientWithRoute Proxy req mval =
169 clientWithRoute Proxy req mval =
166 clientWithRoute (Proxy :: Proxy sublayout) $
170 clientWithRoute (Proxy :: Proxy sublayout) $
167− maybe req (\value -> addHeader hname value req) mval
171+ maybe req (\value -> Servant.Common.Req.addHeader hname value req) mval
169 where hname = symbolVal (Proxy :: Proxy sym)
173 where hname = symbolVal (Proxy :: Proxy sym)
@@ -173,7 +177,7 @@ instance (KnownSymbol sym, ToText a, HasClient sublayout)
173-- will just require an argument that specifies the scheme, host
177-- will just require an argument that specifies the scheme, host
174-- and port to send the request to.
178-- and port to send the request to.
175instance (MimeUnrender ct a) => HasClient (Post (ct ': cts) a) where
179instance (MimeUnrender ct a) => HasClient (Post (ct ': cts) a) where
176− type Client (Post (ct ': cts) a) = BaseUrl -> EitherT ServantError IO a
180+ type Client' (Post (ct ': cts) a) = BaseUrl -> EitherT ServantError IO a
178 clientWithRoute Proxy req uri =
182 clientWithRoute Proxy req uri =
179 performRequestCT (Proxy :: Proxy ct) H.methodPost req [200,201] uri
183 performRequestCT (Proxy :: Proxy ct) H.methodPost req [200,201] uri
@@ -181,7 +185,7 @@ instance (MimeUnrender ct a) => HasClient (Post (ct ': cts) a) where
181-- | If you have a 'Post xs ()' endpoint, the client expects a 204 No Content
185-- | If you have a 'Post xs ()' endpoint, the client expects a 204 No Content
182-- HTTP header.
186-- HTTP header.
183instance HasClient (Post (ct ': cts) ()) where
187instance HasClient (Post (ct ': cts) ()) where
184− type Client (Post (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
188+ type Client' (Post (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
185 clientWithRoute Proxy req host =
189 clientWithRoute Proxy req host =
186 void $ performRequestNoBody H.methodPost req [204] host
190 void $ performRequestNoBody H.methodPost req [204] host
@@ -190,7 +194,7 @@ instance HasClient (Post (ct ': cts) ()) where
190-- will just require an argument that specifies the scheme, host
194-- will just require an argument that specifies the scheme, host
191-- and port to send the request to.
195-- and port to send the request to.
192instance (MimeUnrender ct a) => HasClient (Put (ct ': cts) a) where
196instance (MimeUnrender ct a) => HasClient (Put (ct ': cts) a) where
193− type Client (Put (ct ': cts) a) = BaseUrl -> EitherT ServantError IO a
197+ type Client' (Put (ct ': cts) a) = BaseUrl -> EitherT ServantError IO a
195 clientWithRoute Proxy req host =
199 clientWithRoute Proxy req host =
196 performRequestCT (Proxy :: Proxy ct) H.methodPut req [200,201] host
200 performRequestCT (Proxy :: Proxy ct) H.methodPut req [200,201] host
@@ -198,7 +202,7 @@ instance (MimeUnrender ct a) => HasClient (Put (ct ': cts) a) where
198-- | If you have a 'Put xs ()' endpoint, the client expects a 204 No Content
202-- | If you have a 'Put xs ()' endpoint, the client expects a 204 No Content
199-- HTTP header.
203-- HTTP header.
200instance HasClient (Put (ct ': cts) ()) where
204instance HasClient (Put (ct ': cts) ()) where
201− type Client (Put (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
205+ type Client' (Put (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
202 clientWithRoute Proxy req host =
206 clientWithRoute Proxy req host =
203 void $ performRequestNoBody H.methodPut req [204] host
207 void $ performRequestNoBody H.methodPut req [204] host
@@ -207,7 +211,7 @@ instance HasClient (Put (ct ': cts) ()) where
207-- will just require an argument that specifies the scheme, host
211-- will just require an argument that specifies the scheme, host
208-- and port to send the request to.
212-- and port to send the request to.
209instance (MimeUnrender ct a) => HasClient (Patch (ct ': cts) a) where
213instance (MimeUnrender ct a) => HasClient (Patch (ct ': cts) a) where
210− type Client (Patch (ct ': cts) a) = BaseUrl -> EitherT ServantError IO a
214+ type Client' (Patch (ct ': cts) a) = BaseUrl -> EitherT ServantError IO a
212 clientWithRoute Proxy req host =
216 clientWithRoute Proxy req host =
213 performRequestCT (Proxy :: Proxy ct) H.methodPatch req [200,201] host
217 performRequestCT (Proxy :: Proxy ct) H.methodPatch req [200,201] host
@@ -215,7 +219,7 @@ instance (MimeUnrender ct a) => HasClient (Patch (ct ': cts) a) where
215-- | If you have a 'Patch xs ()' endpoint, the client expects a 204 No Content
219-- | If you have a 'Patch xs ()' endpoint, the client expects a 204 No Content
216-- HTTP header.
220-- HTTP header.
217instance HasClient (Patch (ct ': cts) ()) where
221instance HasClient (Patch (ct ': cts) ()) where
218− type Client (Patch (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
222+ type Client' (Patch (ct ': cts) ()) = BaseUrl -> EitherT ServantError IO ()
219 clientWithRoute Proxy req host =
223 clientWithRoute Proxy req host =
220 void $ performRequestNoBody H.methodPatch req [204] host
224 void $ performRequestNoBody H.methodPatch req [204] host
@@ -247,8 +251,8 @@ instance HasClient (Patch (ct ': cts) ()) where
247instance (KnownSymbol sym, ToText a, HasClient sublayout)
251instance (KnownSymbol sym, ToText a, HasClient sublayout)
248 => HasClient (QueryParam sym a :> sublayout) where
252 => HasClient (QueryParam sym a :> sublayout) where
250− type Client (QueryParam sym a :> sublayout) =
254+ type Client' (QueryParam sym a :> sublayout) =
251− Maybe a -> Client sublayout
255+ Maybe a -> Client' sublayout
253 -- if mparam = Nothing, we don't add it to the query string
257 -- if mparam = Nothing, we don't add it to the query string
254 clientWithRoute Proxy req mparam =
258 clientWithRoute Proxy req mparam =
@@ -289,8 +293,8 @@ instance (KnownSymbol sym, ToText a, HasClient sublayout)
289instance (KnownSymbol sym, ToText a, HasClient sublayout)
293instance (KnownSymbol sym, ToText a, HasClient sublayout)
290 => HasClient (QueryParams sym a :> sublayout) where
294 => HasClient (QueryParams sym a :> sublayout) where
292− type Client (QueryParams sym a :> sublayout) =
296+ type Client' (QueryParams sym a :> sublayout) =
293− [a] -> Client sublayout
297+ [a] -> Client' sublayout
295 clientWithRoute Proxy req paramlist =
299 clientWithRoute Proxy req paramlist =
296 clientWithRoute (Proxy :: Proxy sublayout) $
300 clientWithRoute (Proxy :: Proxy sublayout) $
@@ -324,8 +328,8 @@ instance (KnownSymbol sym, ToText a, HasClient sublayout)
324instance (KnownSymbol sym, HasClient sublayout)
328instance (KnownSymbol sym, HasClient sublayout)
325 => HasClient (QueryFlag sym :> sublayout) where
329 => HasClient (QueryFlag sym :> sublayout) where
327− type Client (QueryFlag sym :> sublayout) =
331+ type Client' (QueryFlag sym :> sublayout) =
328− Bool -> Client sublayout
332+ Bool -> Client' sublayout
330 clientWithRoute Proxy req flag =
334 clientWithRoute Proxy req flag =
331 clientWithRoute (Proxy :: Proxy sublayout) $
335 clientWithRoute (Proxy :: Proxy sublayout) $
@@ -363,8 +367,8 @@ instance (KnownSymbol sym, HasClient sublayout)
363instance (KnownSymbol sym, ToText a, HasClient sublayout)
367instance (KnownSymbol sym, ToText a, HasClient sublayout)
364 => HasClient (MatrixParam sym a :> sublayout) where
368 => HasClient (MatrixParam sym a :> sublayout) where
366− type Client (MatrixParam sym a :> sublayout) =
370+ type Client' (MatrixParam sym a :> sublayout) =
367− Maybe a -> Client sublayout
371+ Maybe a -> Client' sublayout
369 -- if mparam = Nothing, we don't add it to the query string
373 -- if mparam = Nothing, we don't add it to the query string
370 clientWithRoute Proxy req mparam =
374 clientWithRoute Proxy req mparam =
@@ -404,8 +408,8 @@ instance (KnownSymbol sym, ToText a, HasClient sublayout)
404instance (KnownSymbol sym, ToText a, HasClient sublayout)
408instance (KnownSymbol sym, ToText a, HasClient sublayout)
405 => HasClient (MatrixParams sym a :> sublayout) where
409 => HasClient (MatrixParams sym a :> sublayout) where
407− type Client (MatrixParams sym a :> sublayout) =
411+ type Client' (MatrixParams sym a :> sublayout) =
408− [a] -> Client sublayout
412+ [a] -> Client' sublayout
410 clientWithRoute Proxy req paramlist =
414 clientWithRoute Proxy req paramlist =
411 clientWithRoute (Proxy :: Proxy sublayout) $
415 clientWithRoute (Proxy :: Proxy sublayout) $
@@ -439,8 +443,8 @@ instance (KnownSymbol sym, ToText a, HasClient sublayout)
439instance (KnownSymbol sym, HasClient sublayout)
443instance (KnownSymbol sym, HasClient sublayout)
440 => HasClient (MatrixFlag sym :> sublayout) where
444 => HasClient (MatrixFlag sym :> sublayout) where
442− type Client (MatrixFlag sym :> sublayout) =
446+ type Client' (MatrixFlag sym :> sublayout) =
443− Bool -> Client sublayout
447+ Bool -> Client' sublayout
445 clientWithRoute Proxy req flag =
449 clientWithRoute Proxy req flag =
446 clientWithRoute (Proxy :: Proxy sublayout) $
450 clientWithRoute (Proxy :: Proxy sublayout) $
@@ -453,9 +457,9 @@ instance (KnownSymbol sym, HasClient sublayout)
453-- | Pick a 'Method' and specify where the server you want to query is. You get
457-- | Pick a 'Method' and specify where the server you want to query is. You get
454-- back the full `Response`.
458-- back the full `Response`.
455instance HasClient Raw where
459instance HasClient Raw where
456− type Client Raw = H.Method -> BaseUrl -> EitherT ServantError IO (Int, ByteString, MediaType, Response ByteString)
460+ type Client' Raw = H.Method -> BaseUrl -> EitherT ServantError IO (Int, ByteString, MediaType, Response ByteString)
458− clientWithRoute :: Proxy Raw -> Req -> Client Raw
462+ clientWithRoute :: Proxy Raw -> Req -> Client' Raw
459 clientWithRoute Proxy req httpMethod host = do
463 clientWithRoute Proxy req httpMethod host = do
460 performRequest httpMethod req (const True) host
464 performRequest httpMethod req (const True) host
@@ -480,17 +484,17 @@ instance HasClient Raw where
480instance (MimeRender ct a, HasClient sublayout)
484instance (MimeRender ct a, HasClient sublayout)
481 => HasClient (ReqBody (ct ': cts) a :> sublayout) where
485 => HasClient (ReqBody (ct ': cts) a :> sublayout) where
483− type Client (ReqBody (ct ': cts) a :> sublayout) =
487+ type Client' (ReqBody (ct ': cts) a :> sublayout) =
484− a -> Client sublayout
488+ a -> Client' sublayout
486 clientWithRoute Proxy req body =
490 clientWithRoute Proxy req body =
487 clientWithRoute (Proxy :: Proxy sublayout) $ do
491 clientWithRoute (Proxy :: Proxy sublayout) $ do
488 let ctProxy = Proxy :: Proxy ct
492 let ctProxy = Proxy :: Proxy ct
489− setRQBody (toByteString ctProxy body) (contentType ctProxy) req
493+ setRQBody (mimeRender ctProxy body) (contentType ctProxy) req
491-- | Make the querying function append @path@ to the request path.
495-- | Make the querying function append @path@ to the request path.
492instance (KnownSymbol path, HasClient sublayout) => HasClient (path :> sublayout) where
496instance (KnownSymbol path, HasClient sublayout) => HasClient (path :> sublayout) where
493− type Client (path :> sublayout) = Client sublayout
497+ type Client' (path :> sublayout) = Client' sublayout
495 clientWithRoute Proxy req =
499 clientWithRoute Proxy req =
496 clientWithRoute (Proxy :: Proxy sublayout) $
500 clientWithRoute (Proxy :: Proxy sublayout) $