packages feed

servant-client 0.2.1 → 0.2.2

raw patch · 3 files changed

+134/−9 lines, 3 filesdep +http-client-tlsdep ~QuickCheckdep ~servantdep ~servant-servernew-uploader

Dependencies added: http-client-tls

Dependency ranges changed: QuickCheck, servant, servant-server

Files

servant-client.cabal view
@@ -1,5 +1,5 @@ name:                servant-client-version:             0.2.1+version:             0.2.2 synopsis: automatical derivation of querying functions for servant webservices description:   This library lets you derive automatically Haskell functions that@@ -44,10 +44,11 @@     , either     , exceptions     , http-client+    , http-client-tls     , http-types     , network-uri >= 2.6     , safe-    , servant >= 0.2.1+    , servant >= 0.2.2 && < 0.3     , string-conversions     , text     , transformers@@ -71,9 +72,9 @@     , hspec == 2.*     , http-types     , network >= 2.6-    , QuickCheck+    , QuickCheck >= 2.7     , servant >= 0.2.1     , servant-client-    , servant-server >= 0.2.1+    , servant-server >= 0.2.1 && < 0.3     , wai     , warp
src/Servant/Client.hs view
@@ -13,6 +13,7 @@   , module Servant.Common.BaseUrl   ) where +import Control.Monad import Control.Monad.Trans.Either import Data.Aeson import Data.ByteString.Lazy (ByteString)@@ -108,7 +109,7 @@   type Client Delete = BaseUrl -> EitherT String IO ()    clientWithRoute Proxy req host =-    performRequestJSON H.methodDelete req 204 host+    void $ performRequest H.methodDelete req (== 204) host  -- | If you have a 'Get' endpoint in your API, the client -- side querying function that is created when calling 'client'@@ -210,7 +211,7 @@   -- if mparam = Nothing, we don't add it to the query string   clientWithRoute Proxy req mparam =     clientWithRoute (Proxy :: Proxy sublayout) $-      appendToQueryString pname mparamText req+      maybe req (flip (appendToQueryString pname) req . Just) mparamText      where pname  = cs pname'           pname' = symbolVal (Proxy :: Proxy sym)@@ -251,7 +252,7 @@    clientWithRoute Proxy req paramlist =     clientWithRoute (Proxy :: Proxy sublayout) $-      foldl' (\ value req' -> appendToQueryString pname req' value) req paramlist'+      foldl' (\ req' -> maybe req' (flip (appendToQueryString pname) req' . Just)) req paramlist'      where pname  = cs pname'           pname' = symbolVal (Proxy :: Proxy sym)@@ -288,6 +289,121 @@     clientWithRoute (Proxy :: Proxy sublayout) $       if flag         then appendToQueryString paramname Nothing req+        else req++    where paramname = cs $ symbolVal (Proxy :: Proxy sym)++-- | If you use a 'MatrixParam' in one of your endpoints in your API,+-- the corresponding querying function will automatically take+-- an additional argument of the type specified by your 'MatrixParam',+-- enclosed in Maybe.+--+-- If you give Nothing, nothing will be added to the query string.+--+-- If you give a non-'Nothing' value, this function will take care+-- of inserting a textual representation of this value in the query string.+--+-- You can control how values for your type are turned into+-- text by specifying a 'ToText' instance for your type.+--+-- Example:+--+-- > type MyApi = "books" :> MatrixParam "author" Text :> Get [Book]+-- >+-- > myApi :: Proxy MyApi+-- > myApi = Proxy+-- >+-- > getBooksBy :: Maybe Text -> BaseUrl -> EitherT String IO [Book]+-- > getBooksBy = client myApi+-- > -- then you can just use "getBooksBy" to query that endpoint.+-- > -- 'getBooksBy Nothing' for all books+-- > -- 'getBooksBy (Just "Isaac Asimov")' to get all books by Isaac Asimov+instance (KnownSymbol sym, ToText a, HasClient sublayout)+      => HasClient (MatrixParam sym a :> sublayout) where++  type Client (MatrixParam sym a :> sublayout) =+    Maybe a -> Client sublayout++  -- if mparam = Nothing, we don't add it to the query string+  clientWithRoute Proxy req mparam =+    clientWithRoute (Proxy :: Proxy sublayout) $+      maybe req (flip (appendToMatrixParams pname . Just) req) mparamText++    where pname = symbolVal (Proxy :: Proxy sym)+          mparamText = fmap (cs . toText) mparam++-- | If you use a 'MatrixParams' in one of your endpoints in your API,+-- the corresponding querying function will automatically take an+-- additional argument, a list of values of the type specified by your+-- 'MatrixParams'.+--+-- If you give an empty list, nothing will be added to the query string.+--+-- Otherwise, this function will take care of inserting a textual+-- representation of your values in the path segment string, under the+-- same matrix string parameter name.+--+-- You can control how values for your type are turned into text by+-- specifying a 'ToText' instance for your type.+--+-- Example:+--+-- > type MyApi = "books" :> MatrixParams "authors" Text :> Get [Book]+-- >+-- > myApi :: Proxy MyApi+-- > myApi = Proxy+-- >+-- > getBooksBy :: [Text] -> BaseUrl -> EitherT String IO [Book]+-- > getBooksBy = client myApi+-- > -- then you can just use "getBooksBy" to query that endpoint.+-- > -- 'getBooksBy []' for all books+-- > -- 'getBooksBy ["Isaac Asimov", "Robert A. Heinlein"]'+-- > --   to get all books by Asimov and Heinlein+instance (KnownSymbol sym, ToText a, HasClient sublayout)+      => HasClient (MatrixParams sym a :> sublayout) where++  type Client (MatrixParams sym a :> sublayout) =+    [a] -> Client sublayout++  clientWithRoute Proxy req paramlist =+    clientWithRoute (Proxy :: Proxy sublayout) $+      foldl' (\ req' value -> maybe req' (flip (appendToMatrixParams pname) req' . Just . cs) value) req paramlist'++    where pname  = cs pname'+          pname' = symbolVal (Proxy :: Proxy sym)+          paramlist' = map (Just . toText) paramlist++-- | If you use a 'MatrixFlag' in one of your endpoints in your API,+-- the corresponding querying function will automatically take an+-- additional 'Bool' argument.+--+-- If you give 'False', nothing will be added to the path segment.+--+-- Otherwise, this function will insert a value-less matrix parameter+-- under the name associated to your 'MatrixFlag'.+--+-- Example:+--+-- > type MyApi = "books" :> MatrixFlag "published" :> Get [Book]+-- >+-- > myApi :: Proxy MyApi+-- > myApi = Proxy+-- >+-- > getBooks :: Bool -> BaseUrl -> EitherT String IO [Book]+-- > getBooks = client myApi+-- > -- then you can just use "getBooks" to query that endpoint.+-- > -- 'getBooksBy False' for all books+-- > -- 'getBooksBy True' to only get _already published_ books+instance (KnownSymbol sym, HasClient sublayout)+      => HasClient (MatrixFlag sym :> sublayout) where++  type Client (MatrixFlag sym :> sublayout) =+    Bool -> Client sublayout++  clientWithRoute Proxy req flag =+    clientWithRoute (Proxy :: Proxy sublayout) $+      if flag+        then appendToMatrixParams paramname Nothing req         else req      where paramname = cs $ symbolVal (Proxy :: Proxy sym)
src/Servant/Common/Req.hs view
@@ -19,6 +19,7 @@ import Data.Text import Data.Text.Encoding import Network.HTTP.Client+import Network.HTTP.Client.TLS import Network.HTTP.Types import Network.URI import Servant.Common.BaseUrl@@ -41,6 +42,13 @@ appendToPath p req =   req { reqPath = reqPath req ++ "/" ++ p } +appendToMatrixParams :: String+                     -> Maybe String+                     -> Req+                     -> Req+appendToMatrixParams pname pvalue req =+  req { reqPath = reqPath req ++ ";" ++ pname ++ maybe "" ("=" ++) pvalue }+ appendToQueryString :: Text       -- ^ param name                     -> Maybe Text -- ^ param value                     -> Req@@ -77,14 +85,14 @@         setheaders r = r { requestHeaders = Prelude.map toProperHeader (headers req) }          toProperHeader (name, val) =-          (fromString name, encodeUtf8 val) +          (fromString name, encodeUtf8 val)   -- * performing requests  {-# NOINLINE __manager #-} __manager :: MVar Manager-__manager = unsafePerformIO (newManager defaultManagerSettings >>= newMVar)+__manager = unsafePerformIO (newManager tlsManagerSettings >>= newMVar)  __withGlobalManager :: (Manager -> IO a) -> IO a __withGlobalManager action = modifyMVar __manager $ \ manager -> do