-- | This module provides functions that take API endpoint types and transform them into -- HTTP Response outputs. -- {-# LANGUAGE AllowAmbiguousTypes #-} module Hreq.Core.Client.Internal where import Control.Monad.Except import Data.Proxy import Hreq.Core.API import Hreq.Core.Client.ClientError import Hreq.Core.Client.HasRequest import Hreq.Core.Client.HasResponse import Hreq.Core.Client.Request import Hreq.Core.Client.RunClient -- | 'HasClient' represent constraints required to interpret a type level API into an actual -- HTTP network request. -- -- @ts ~@ 'ApiToReq' @api@ : Turns API description into a list of Request Content types -- -- @v ~ 'GetVerb' api@ : Retrieves the verb component of an API definition -- -- 'HasRequest' @ts v@ : Interprets type level list 'ReqContent' and 'Verb' components to obtain 'Request' Data -- -- 'HasResponse' @v n@ : Interprets 'Verb' component to obtain type level specified Response -- -- 'MonadError' 'ClientError' @n@ : @MonadError ClientError n@ is used by the 'httpRes' function -- -- 'RunClient' @m@ : Provides capability to make an actual Http client network request -- type HasClient api ts v n m = ( ts ~ ApiToReq api , v ~ GetVerb api , HasRequest ts v , HasResponse v n , MonadError ClientError n , RunClient m ) -- | Used to make generic HTTP requests -- hreq' :: forall api ts v m. HasClient api ts v (Either ClientError) m => Proxy api -> HttpInput ts -> m (HttpOutput v) hreq' _ reqInput = do let req = httpReq (Proxy @v) (Proxy @ts) reqInput defaultRequest clientResponse <- runClient $! req lift' $ httpRes (Proxy @v) clientResponse where lift' = either throwHttpError pure -- | Used to make HTTP requests. Uses visible type-applications for API type specification. -- Example -- -- > hreq @(Capture "age" Int :> GetJson Value) (25 :. Empty) -- hreq :: forall api ts v m. HasClient api ts v (Either ClientError) m => HttpInput ts -> m (HttpOutput v) hreq = hreq' (Proxy @api) -- | 'HasStreamingClient' type constraint is represents constraints required for streaming HTTP responses. -- -- @ts ~@ 'ApiToReq' @api@ : Turns API description into a list of Request Content types -- -- @v ~@ 'GetVerb' @api@ : Retrieves the verb component of an API definition -- -- 'HasRequest' @ts v@ : Interprets type level list 'ReqContent' and 'Verb' components to obtain -- -- 'RunStreamingClient' @m a@: Provides capability to create an HTTP request with response streaming. -- type HasStreamingClient api a ts v m = ( ts ~ ApiToReq api , v ~ GetVerb api , HasRequest ts v , RunStreamingClient m a ) -- | Helper function for working with an HTTP response streaming client. -- hreqStream :: forall api a ts v m r. (HasStreamingClient api a ts v m) => Proxy api -> HttpInput ts -> (a -> IO r) -> m r hreqStream _ reqInput f = do let req = httpReq (Proxy @v) (Proxy @ts) reqInput defaultRequest withStreamingClient req (liftIO . f)