on master help sign in
Add parameter-supplying operator
d81c8d9Gaël Deest
servant-client-core/src/Servant/Client/Core/HasClient.hs+48−7
@@ -27,6 +27,7 @@ module Servant.Client.Core.HasClient (
27 HasClient (..),
27 HasClient (..),
28 EmptyClient (..),
28 EmptyClient (..),
29 AsClientT,
29 AsClientT,
30+ (//),
30 (/:),
31 (/:),
31 foldMapUnion,
32 foldMapUnion,
32 matchUnion,
33 matchUnion,
@@ -54,7 +55,8 @@ import Data.Sequence
54 (fromList)
55 (fromList)
55import qualified Data.Text as T
56import qualified Data.Text as T
56import Network.HTTP.Media
57import Network.HTTP.Media
57− (MediaType, matches, parseAccept, (//))
58+ (MediaType, matches, parseAccept)
59+import qualified Network.HTTP.Media as Media
58import qualified Data.Sequence as Seq
60import qualified Data.Sequence as Seq
59import Data.SOP.BasicFunctors
61import Data.SOP.BasicFunctors
60 (I (I), (:.:) (Comp))
62 (I (I), (:.:) (Comp))
@@ -873,9 +875,12 @@ instance
873
875
874#endif
876#endif
875
877
876−infixl 1 /:
878+infixl 1 //
879+infixl 2 /:
877
880
878−-- | Convenience function for working with nested record-clients.
881+-- | Helper to make code using records of clients more readable.
882+--
883+-- Can be mixed with (/:) for supplying arguments.
879--
884--
880-- Example:
885-- Example:
881--
886--
@@ -899,10 +904,46 @@ infixl 1 /:
899-- rootClient = client api
904-- rootClient = client api
900--
905--
901-- endpointClient :: ClientM Person
906-- endpointClient :: ClientM Person
902−-- endpointClient = client /: subApi /: endpoint
907+-- endpointClient = client // subApi // endpoint
908+-- @@
909+(//) :: a -> (a -> b) -> b
910+x // f = f x
911+
912+-- | Convenience function for supplying arguments to client functions when
913+-- working with records of clients.
914+--
915+-- Intended to be use in conjunction with '(//)'.
916+--
917+-- Example:
918+--
919+-- @@
920+-- type Api = NamedAPI RootApi
921+--
922+-- data RootApi mode = RootApi
923+-- { subApi :: mode :- Capture "token" String :> NamedAPI SubApi
924+-- , hello :: mode :- Capture "name" String :> Get '[JSON] String
925+-- , …
926+-- } deriving Generic
927+--
928+-- data SubAmi mode = SubApi
929+-- { endpoint :: mode :- Get '[JSON] Person
930+-- , …
931+-- } deriving Generic
932+--
933+-- api :: Proxy API
934+-- api = Proxy
935+--
936+-- rootClient :: RootApi (AsClientT ClientM)
937+-- rootClient = client api
938+--
939+-- hello :: String -> ClientM String
940+-- hello name = rootClient // hello /: name
941+--
942+-- endpointClient :: ClientM Person
943+-- endpointClient = client // subApi /: "foobar123" // endpoint
903-- @@
944-- @@
904−(/:) :: a -> (a -> b) -> b
945+(/:) :: (a -> b -> c) -> b -> a -> c
905−x /: f = f x
946+(/:) = flip
906
947
907
948
908{- Note [Non-Empty Content Types]
949{- Note [Non-Empty Content Types]
@@ -928,7 +969,7 @@ for empty and one for non-empty lists).
928checkContentTypeHeader :: RunClient m => Response -> m MediaType
969checkContentTypeHeader :: RunClient m => Response -> m MediaType
929checkContentTypeHeader response =
970checkContentTypeHeader response =
930 case lookup "Content-Type" $ toList $ responseHeaders response of
971 case lookup "Content-Type" $ toList $ responseHeaders response of
931− Nothing -> return $ "application"//"octet-stream"
972+ Nothing -> return $ "application" Media.// "octet-stream"
932 Just t -> case parseAccept t of
973 Just t -> case parseAccept t of
933 Nothing -> throwClientError $ InvalidContentTypeHeader response
974 Nothing -> throwClientError $ InvalidContentTypeHeader response
934 Just t' -> return t'
975 Just t' -> return t'
servant-client-core/src/Servant/Client/Core/Reexport.hs+1
@@ -8,6 +8,7 @@ module Servant.Client.Core.Reexport
8 , foldMapUnion
8 , foldMapUnion
9 , matchUnion
9 , matchUnion
10 , AsClientT
10 , AsClientT
11+ , (//)
11 , (/:)
12 , (/:)
12
13
13 -- * Response (for @Raw@)
14 -- * Response (for @Raw@)
servant-client/test/Servant/ClientTestUtils.hs+2−2
@@ -111,7 +111,7 @@ type TestHeaders = '[Header "X-Example1" Int, Header "X-Example2" String]
111data RecordRoutes mode = RecordRoutes
111data RecordRoutes mode = RecordRoutes
112 { version :: mode :- "version" :> Get '[JSON] Int
112 { version :: mode :- "version" :> Get '[JSON] Int
113 , echo :: mode :- "echo" :> Capture "string" String :> Get '[JSON] String
113 , echo :: mode :- "echo" :> Capture "string" String :> Get '[JSON] String
114− , otherRoutes :: mode :- "other" :> NamedRoutes OtherRoutes
114+ , otherRoutes :: mode :- "other" :> Capture "someParam" Int :> NamedRoutes OtherRoutes
115 } deriving Generic
115 } deriving Generic
116
116
117data OtherRoutes mode = OtherRoutes
117data OtherRoutes mode = OtherRoutes
@@ -246,7 +246,7 @@ server = serve api (
246 :<|> RecordRoutes
246 :<|> RecordRoutes
247 { version = pure 42
247 { version = pure 42
248 , echo = pure
248 , echo = pure
249− , otherRoutes = OtherRoutes
249+ , otherRoutes = \_ -> OtherRoutes
250 { something = pure ["foo", "bar", "pweet"]
250 { something = pure ["foo", "bar", "pweet"]
251 }
251 }
252 }
252 }
servant-client/test/Servant/GenericSpec.hs+4−4
@@ -19,7 +19,7 @@ module Servant.GenericSpec (spec) where
19
19
20import Test.Hspec
20import Test.Hspec
21
21
22−import Servant.Client ((/:))
22+import Servant.Client ((//), (/:))
23import Servant.ClientTestUtils
23import Servant.ClientTestUtils
24
24
25spec :: Spec
25spec :: Spec
@@ -31,7 +31,7 @@ genericSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
31 context "Record clients work as expected" $ do
31 context "Record clients work as expected" $ do
32
32
33 it "Client functions return expected values" $ \(_,baseUrl) -> do
33 it "Client functions return expected values" $ \(_,baseUrl) -> do
34− runClient (recordRoutes /: version) baseUrl `shouldReturn` Right 42
34+ runClient (recordRoutes // version) baseUrl `shouldReturn` Right 42
35− runClient (recordRoutes /: echo $ "foo") baseUrl `shouldReturn` Right "foo"
35+ runClient (recordRoutes // echo /: "foo") baseUrl `shouldReturn` Right "foo"
36 it "Clients can be nested" $ \(_,baseUrl) -> do
36 it "Clients can be nested" $ \(_,baseUrl) -> do
37− runClient (recordRoutes /: otherRoutes /: something) baseUrl `shouldReturn` Right ["foo", "bar", "pweet"]
37+ runClient (recordRoutes // otherRoutes /: 42 // something) baseUrl `shouldReturn` Right ["foo", "bar", "pweet"]