symantic-http-client 0.0.0.20190324 → 0.0.1.20190410
raw patch · 2 files changed
+60/−38 lines, 2 filesdep ~base64-bytestringdep ~symantic-httpPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base64-bytestring, symantic-http
API changes (from Hackage documentation)
+ Symantic.HTTP.Client: class ClientConnectionClass a (ts :: [*]) where {
+ Symantic.HTTP.Client: instance Symantic.HTTP.API.HTTP_Raw Symantic.HTTP.Client.Client
+ Symantic.HTTP.Client: instance Symantic.HTTP.Client.ClientConnectionClass Symantic.HTTP.Client.ClientResponse '[]
+ Symantic.HTTP.Client: instance Symantic.HTTP.Client.ClientConnectionClass a (t : ts)
+ Symantic.HTTP.Client: type family ClientConnectionConstraint a ts :: Constraint;
+ Symantic.HTTP.Client: }
- Symantic.HTTP.Client: Client :: ((ClientModifier -> k) -> requests) -> Client requests k
+ Symantic.HTTP.Client: Client :: ((ClientModifier -> k) -> callers) -> Client callers k
- Symantic.HTTP.Client: ClientError_DecodeFailure :: Text -> ClientResponse -> ClientError
+ Symantic.HTTP.Client: ClientError_DecodeFailure :: String -> ClientResponse -> ClientError
- Symantic.HTTP.Client: [unClient] :: Client requests k -> (ClientModifier -> k) -> requests
+ Symantic.HTTP.Client: [unClient] :: Client callers k -> (ClientModifier -> k) -> callers
- Symantic.HTTP.Client: client :: Client requests ClientRequest -> requests
+ Symantic.HTTP.Client: client :: Client callers ClientRequest -> callers
- Symantic.HTTP.Client: clientConnection :: forall a ts. MimeTypes ts (MimeDecodable a) => (Proxy ts -> Proxy a -> ClientRequest) -> ClientConnection a
+ Symantic.HTTP.Client: clientConnection :: (ClientConnectionClass a ts, ClientConnectionConstraint a ts) => (Proxy ts -> Proxy a -> ClientRequest) -> ClientConnection a
- Symantic.HTTP.Client: newtype Client requests k
+ Symantic.HTTP.Client: newtype Client callers k
- Symantic.HTTP.Client: runClient :: MimeTypes ts (MimeDecodable a) => ClientEnv -> (Proxy ts -> Proxy a -> ClientRequest) -> IO (Either ClientError a)
+ Symantic.HTTP.Client: runClient :: ClientConnectionConstraint a ts => ClientConnectionClass a ts => ClientEnv -> (Proxy ts -> Proxy a -> ClientRequest) -> IO (Either ClientError a)
Files
- Symantic/HTTP/Client.hs +56/−34
- symantic-http-client.cabal +4/−4
Symantic/HTTP/Client.hs view
@@ -17,12 +17,12 @@ import Data.Foldable (null, for_, toList) import Data.Function (($), (.), id, on) import Data.Functor (Functor(..), (<$>))+import Data.Kind (Constraint) import Data.Maybe (Maybe(..), maybe, fromMaybe) import Data.Ord (Ord(..)) import Data.Proxy (Proxy(..)) import Data.Semigroup (Semigroup(..))-import Data.String (IsString(..))-import Data.Text (Text)+import Data.String (IsString(..), String) import Data.Traversable (sequence) import Data.Tuple (fst) import GHC.Exts (fromList)@@ -42,7 +42,6 @@ import qualified Data.List as List import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Sequence as Seq-import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import qualified Data.Time.Clock as Time import qualified Network.HTTP.Client as Client@@ -56,20 +55,20 @@ import Symantic.HTTP.MIME -- * Type 'Client'--- | @'Client' a k@ is a recipe to produce a 'ClientRequest'--- from arguments 'requests' (one per number of alternative routes)+-- | (@'Client' a k@) is a recipe to produce a 'ClientRequest'+-- from returned ('callers') (one per number of alternative routes) -- separated by (':!:'). ----- 'Client' is analogous to a printf using a format customized for HTTP routing.-newtype Client requests k+-- 'Client' is analogous to a printf using the API as a format customized for HTTP routing.+newtype Client callers k = Client- { unClient :: (ClientModifier -> k) -> requests+ { unClient :: (ClientModifier -> k) -> callers } --- | @'client' requests@ returns the 'ClientRequest'+-- | @'client' callers@ returns the 'ClientRequest' -- builders from the given API.-client :: Client requests ClientRequest -> requests-client (Client requests) = requests ($ ini)+client :: Client callers ClientRequest -> callers+client (Client callers) = callers ($ ini) where ini = ClientRequest { clientReq_httpVersion = HTTP.http11@@ -114,7 +113,14 @@ instance HTTP_Header Client where header n = Client $ \k v -> k $ \req -> req{ clientReq_headers = clientReq_headers req Seq.|> (n, Web.toHeader v) }+instance HTTP_Raw Client where+ type RawConstraint Client = ()+ type RawArgs Client = HTTP.Method -> Proxy ('[]::[*]) -> Proxy ClientResponse -> ClientRequest+ type Raw Client = ClientRequest+ raw = Client $ \k meth Proxy Proxy -> k $ \req ->+ req{ clientReq_method = meth } instance HTTP_BasicAuth Client where+ type BasicAuthConstraint Client a = () type BasicAuthArgs Client a k = BasicAuthUser -> BasicAuthPass -> k basicAuth' realm = Client $ \k user pass -> k $ \req -> req{ clientReq_headers =@@ -201,9 +207,9 @@ HTTP.Method -> repr (ResponseArgs repr a ts) (Response repr)- response m = Client $ \k Proxy Proxy -> k $ \req ->+ response meth = Client $ \k Proxy Proxy -> k $ \req -> req- { clientReq_method = m+ { clientReq_method = meth , clientReq_accept = clientReq_accept req <> fromList (toList $ mediaTypes @ts @(MimeDecodable a))@@ -226,9 +232,9 @@ HTTP.Method -> repr (ResponseStreamArgs repr as ts framing) (ResponseStream repr)- responseStream m = Client $ \k Proxy Proxy Proxy -> k $ \req ->+ responseStream meth = Client $ \k Proxy Proxy Proxy -> k $ \req -> req- { clientReq_method = m+ { clientReq_method = meth , clientReq_accept = clientReq_accept req <> fromList (toList $ mediaTypes @ts @(MimeDecodable (FramingYield as)))@@ -272,7 +278,7 @@ -- | The server returned an error response = ClientError_FailureResponse ClientResponse -- | The body could not be decoded at the expected type- | ClientError_DecodeFailure Text ClientResponse+ | ClientError_DecodeFailure String ClientResponse -- | The content-type of the response is not supported | ClientError_UnsupportedContentType BS.ByteString ClientResponse -- | There was a connection error, and no response was received@@ -342,7 +348,8 @@ -} runClient ::- MimeTypes ts (MimeDecodable a) =>+ ClientConnectionConstraint a ts =>+ ClientConnectionClass a ts => ClientEnv -> (Proxy ts -> Proxy a -> ClientRequest) -> IO (Either ClientError a)@@ -352,23 +359,38 @@ unClientConn . clientConnection -clientConnection ::- forall a ts.- MimeTypes ts (MimeDecodable a) =>- (Proxy ts -> Proxy a -> ClientRequest) ->- ClientConnection a-clientConnection req = do- clientRes <- doClientRequest $ req (Proxy::Proxy ts) (Proxy::Proxy a)- let mtRes =- fromMaybe "application/octet-stream" $- List.lookup "Content-Type" $- Client.responseHeaders clientRes- case matchContent @ts @(MimeDecodable a) mtRes of- Nothing -> MC.throw $ ClientError_UnsupportedContentType mtRes clientRes- Just (MimeType mt) ->- case mimeDecode mt $ Client.responseBody clientRes of- Left err -> MC.throw $ ClientError_DecodeFailure (Text.pack err) clientRes- Right val -> return val+-- ** Class 'ClientConnectionClass'+-- | 'clientConnection' is different when 'ts' is empty:+-- no 'mimeDecode' is performed.+-- This is used by the 'raw' combinator.+class ClientConnectionClass a (ts::[*]) where+ type ClientConnectionConstraint a ts :: Constraint+ clientConnection ::+ ClientConnectionConstraint a ts =>+ (Proxy ts -> Proxy a -> ClientRequest) ->+ ClientConnection a+instance ClientConnectionClass ClientResponse '[] where+ type ClientConnectionConstraint ClientResponse '[] = ()+ clientConnection req = do+ clientRes <- doClientRequest $ req+ (Proxy::Proxy '[])+ (Proxy::Proxy ClientResponse)+ return clientRes+instance ClientConnectionClass a (t ': ts) where+ type ClientConnectionConstraint a (t ': ts) =+ MimeTypes (t ': ts) (MimeDecodable a)+ clientConnection req = do+ clientRes <- doClientRequest $ req (Proxy::Proxy (t ': ts)) (Proxy::Proxy a)+ let mtRes =+ fromMaybe "application/octet-stream" $+ List.lookup "Content-Type" $+ Client.responseHeaders clientRes+ case matchContent @(t ': ts) @(MimeDecodable a) mtRes of+ Nothing -> MC.throw $ ClientError_UnsupportedContentType mtRes clientRes+ Just (MimeType mt) ->+ case mimeDecode mt $ Client.responseBody clientRes of+ Left err -> MC.throw $ ClientError_DecodeFailure err clientRes+ Right a -> return a doClientRequest :: ClientRequest -> ClientConnection ClientResponse doClientRequest clientReq = do
symantic-http-client.cabal view
@@ -2,12 +2,12 @@ -- PVP: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.0.0.20190324+version: 0.0.1.20190410 category: Protocol synopsis: symantic-http applied to the derivation of HTTP clients description: This library applies <https://hackage.haskell.org/package/symantic-http symantic-http>- to the building of an HTTP client (request building and encoding)+ to the building of an HTTP client (request building and response decoding) based upon <https://hackage.haskell.org/package/http-client http-client>. . For learning how to use this library,@@ -60,9 +60,9 @@ -fno-warn-tabs -- -fhide-source-paths build-depends:- symantic-http >= 0.0+ symantic-http >= 0.1.1 , base >= 4.10 && < 5- , base64-bytestring >= 1.0.0.1+ , base64-bytestring >= 1.0 , bytestring >= 0.10 , containers >= 0.5 , http-api-data >= 0.4