hreq-core-0.1.0.0: src/Hreq/Core/Client/Internal.hs
-- | 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)