{-# options_haddock prune #-}

-- |Description: Http Interpreters, Internal
module Polysemy.Http.Interpreter.Native where

import qualified Data.CaseInsensitive as CaseInsensitive
import Data.CaseInsensitive (foldedCase)
import Exon (exon)
import qualified Network.HTTP.Client as HTTP
import Network.HTTP.Client (BodyReader, httpLbs, responseClose, responseOpen)
import Network.HTTP.Client.Internal (CookieJar (CJ))
import Polysemy.Internal.Tactics (liftT)
import qualified Polysemy.Log as Log

import Polysemy.Http.Data.Header (Header (Header), unHeaderName, unHeaderValue)
import qualified Polysemy.Http.Data.HttpError as HttpError
import Polysemy.Http.Data.HttpError (HttpError)
import Polysemy.Http.Data.Request (
  Body (Body),
  Host (Host),
  Path (Path),
  Request (Request),
  Tls (Tls),
  methodUpper,
  unPort,
  unQueryKey,
  unQueryValue,
  )
import Polysemy.Http.Data.Response (Response (Response))
import qualified Polysemy.Http.Effect.Http as Http
import Polysemy.Http.Effect.Http (Http)
import qualified Polysemy.Http.Effect.Manager as Manager
import Polysemy.Http.Effect.Manager (Manager)
import Polysemy.Http.Interpreter.Manager (interpretManager)

-- |Converts a 'Request' to a native 'N.Request'.
nativeRequest :: Request -> HTTP.Request
nativeRequest :: Request -> Request
nativeRequest (Request Method
method (Host Text
host) Maybe Port
portOverride (Tls Bool
tls) (Path Text
path) [(HeaderName, HeaderValue)]
headers (CJ [Cookie]
cookies) [(QueryKey, Maybe QueryValue)]
query (Body LByteString
body)) =
  [(ByteString, Maybe ByteString)] -> Request -> Request
HTTP.setQueryString [(ByteString, Maybe ByteString)]
queryParams Request
HTTP.defaultRequest {
    host :: ByteString
HTTP.host = Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 Text
host,
    port :: Int
HTTP.port = Int
port,
    secure :: Bool
HTTP.secure = Bool
tls,
    method :: ByteString
HTTP.method = Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 (Method -> Text
methodUpper Method
method),
    requestHeaders :: RequestHeaders
HTTP.requestHeaders = RequestHeaders
encodedHeaders,
    path :: ByteString
HTTP.path = Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 Text
path,
    requestBody :: RequestBody
HTTP.requestBody = LByteString -> RequestBody
HTTP.RequestBodyLBS LByteString
body,
    cookieJar :: Maybe CookieJar
HTTP.cookieJar = [Cookie] -> CookieJar
CJ ([Cookie] -> CookieJar)
-> (NonEmpty Cookie -> [Cookie]) -> NonEmpty Cookie -> CookieJar
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Cookie -> [Cookie]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Cookie -> CookieJar)
-> Maybe (NonEmpty Cookie) -> Maybe CookieJar
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Cookie] -> Maybe (NonEmpty Cookie)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [Cookie]
cookies
  }
  where
    queryParams :: [(ByteString, Maybe ByteString)]
queryParams =
      (QueryKey -> ByteString)
-> (Maybe QueryValue -> Maybe ByteString)
-> (QueryKey, Maybe QueryValue)
-> (ByteString, Maybe ByteString)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 (Text -> ByteString)
-> (QueryKey -> Text) -> QueryKey -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryKey -> Text
unQueryKey) ((QueryValue -> ByteString) -> Maybe QueryValue -> Maybe ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 (Text -> ByteString)
-> (QueryValue -> Text) -> QueryValue -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QueryValue -> Text
unQueryValue)) ((QueryKey, Maybe QueryValue) -> (ByteString, Maybe ByteString))
-> [(QueryKey, Maybe QueryValue)]
-> [(ByteString, Maybe ByteString)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(QueryKey, Maybe QueryValue)]
query
    port :: Int
port =
      Int -> (Port -> Int) -> Maybe Port -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (if Bool
tls then Int
443 else Int
80) Port -> Int
unPort Maybe Port
portOverride
    encodedHeaders :: RequestHeaders
encodedHeaders =
      (HeaderName -> CI ByteString)
-> (HeaderValue -> ByteString)
-> (HeaderName, HeaderValue)
-> (CI ByteString, ByteString)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CaseInsensitive.mk (ByteString -> CI ByteString)
-> (HeaderName -> ByteString) -> HeaderName -> CI ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 (Text -> ByteString)
-> (HeaderName -> Text) -> HeaderName -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeaderName -> Text
unHeaderName) (Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 (Text -> ByteString)
-> (HeaderValue -> Text) -> HeaderValue -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeaderValue -> Text
unHeaderValue) ((HeaderName, HeaderValue) -> (CI ByteString, ByteString))
-> [(HeaderName, HeaderValue)] -> RequestHeaders
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(HeaderName, HeaderValue)]
headers

convertResponse :: HTTP.Response b -> Response b
convertResponse :: forall b. Response b -> Response b
convertResponse Response b
response =
  Status -> b -> [Header] -> CookieJar -> Response b
forall b. Status -> b -> [Header] -> CookieJar -> Response b
Response (Response b -> Status
forall body. Response body -> Status
HTTP.responseStatus Response b
response) (Response b -> b
forall body. Response body -> body
HTTP.responseBody Response b
response) [Header]
headers (Response b -> CookieJar
forall body. Response body -> CookieJar
HTTP.responseCookieJar Response b
response)
  where
    headers :: [Header]
headers =
      (CI ByteString, ByteString) -> Header
forall {b} {b}.
(ConvertUtf8 String b, ConvertUtf8 String b) =>
(CI b, b) -> Header
header ((CI ByteString, ByteString) -> Header)
-> RequestHeaders -> [Header]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Response b -> RequestHeaders
forall body. Response body -> RequestHeaders
HTTP.responseHeaders Response b
response
    header :: (CI b, b) -> Header
header (CI b -> b
forall s. CI s -> s
foldedCase -> b -> String
forall a b. ConvertUtf8 a b => b -> a
decodeUtf8 -> String
name, b -> String
forall a b. ConvertUtf8 a b => b -> a
decodeUtf8 -> String
value) =
      HeaderName -> HeaderValue -> Header
Header (String -> HeaderName
forall a. IsString a => String -> a
fromString String
name) (String -> HeaderValue
forall a. IsString a => String -> a
fromString String
value)

internalError ::
  Member (Embed IO) r =>
  IO a ->
  Sem r (Either HttpError a)
internalError :: forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either HttpError a)
internalError =
  (Either Text a -> Either HttpError a)
-> Sem r (Either Text a) -> Sem r (Either HttpError a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Text -> HttpError) -> Either Text a -> Either HttpError a
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Text -> HttpError
HttpError.Internal) (Sem r (Either Text a) -> Sem r (Either HttpError a))
-> (IO a -> Sem r (Either Text a))
-> IO a
-> Sem r (Either HttpError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> Sem r (Either Text a)
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either Text a)
tryAny

executeRequest ::
  Member (Embed IO) r =>
  HTTP.Manager ->
  Request ->
  Sem r (Either HttpError (Response LByteString))
executeRequest :: forall (r :: EffectRow).
Member (Embed IO) r =>
Manager
-> Request -> Sem r (Either HttpError (Response LByteString))
executeRequest Manager
manager Request
request =
  (Response LByteString -> Response LByteString)
-> Either HttpError (Response LByteString)
-> Either HttpError (Response LByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Response LByteString -> Response LByteString
forall b. Response b -> Response b
convertResponse (Either HttpError (Response LByteString)
 -> Either HttpError (Response LByteString))
-> Sem r (Either HttpError (Response LByteString))
-> Sem r (Either HttpError (Response LByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Response LByteString)
-> Sem r (Either HttpError (Response LByteString))
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either HttpError a)
internalError (Request -> Manager -> IO (Response LByteString)
httpLbs (Request -> Request
nativeRequest Request
request) Manager
manager)

withResponse ::
  Members [Embed IO, Log, Resource, Manager] r =>
  Request ->
  (Response BodyReader -> Sem r a) ->
  Sem r (Either HttpError a)
withResponse :: forall (r :: EffectRow) a.
Members '[Embed IO, Log, Resource, Manager] r =>
Request
-> (Response BodyReader -> Sem r a) -> Sem r (Either HttpError a)
withResponse Request
request Response BodyReader -> Sem r a
f =
  Sem r (Either HttpError (Response BodyReader))
-> (Either HttpError (Response BodyReader) -> Sem r ())
-> (Either HttpError (Response BodyReader)
    -> Sem r (Either HttpError a))
-> Sem r (Either HttpError a)
forall (r :: EffectRow) a c b.
Member Resource r =>
Sem r a -> (a -> Sem r c) -> (a -> Sem r b) -> Sem r b
bracket Sem r (Either HttpError (Response BodyReader))
acquire Either HttpError (Response BodyReader) -> Sem r ()
forall {r :: EffectRow} {a} {a}.
(Member (Embed IO) r, Member Log r) =>
Either a (Response a) -> Sem r ()
release Either HttpError (Response BodyReader)
-> Sem r (Either HttpError a)
use
  where
    acquire :: Sem r (Either HttpError (Response BodyReader))
acquire = do
      Manager
manager <- Sem r Manager
forall (r :: EffectRow). Member Manager r => Sem r Manager
Manager.get
      IO (Response BodyReader)
-> Sem r (Either HttpError (Response BodyReader))
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either HttpError a)
internalError (Request -> Manager -> IO (Response BodyReader)
responseOpen (Request -> Request
nativeRequest Request
request) Manager
manager)
    release :: Either a (Response a) -> Sem r ()
release (Right Response a
response) =
      IO () -> Sem r (Either Text ())
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either Text a)
tryAny (Response a -> IO ()
forall a. Response a -> IO ()
responseClose Response a
response) Sem r (Either Text ()) -> (Either Text () -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Text -> Sem r ())
-> (() -> Sem r ()) -> Either Text () -> Sem r ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Sem r ()
forall {r :: EffectRow}. Member Log r => Text -> Sem r ()
closeFailed () -> Sem r ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    release (Left a
_) =
      Sem r ()
forall (f :: * -> *). Applicative f => f ()
unit
    use :: Either HttpError (Response BodyReader)
-> Sem r (Either HttpError a)
use (Right Response BodyReader
response) = do
      a -> Either HttpError a
forall a b. b -> Either a b
Right (a -> Either HttpError a) -> Sem r a -> Sem r (Either HttpError a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Response BodyReader -> Sem r a
f (Response BodyReader -> Response BodyReader
forall b. Response b -> Response b
convertResponse Response BodyReader
response)
    use (Left HttpError
err) =
      Either HttpError a -> Sem r (Either HttpError a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (HttpError -> Either HttpError a
forall a b. a -> Either a b
Left HttpError
err)
    closeFailed :: Text -> Sem r ()
closeFailed Text
err =
      Text -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member Log r) =>
Text -> Sem r ()
Log.error [exon|closing response failed: #{err}|]
{-# inline withResponse #-}

distribEither ::
  Functor f =>
  Either err (f a) ->
  Sem (WithTactics e f m r) (f (Either err a))
distribEither :: forall (f :: * -> *) err a (e :: (* -> *) -> * -> *) (m :: * -> *)
       (r :: EffectRow).
Functor f =>
Either err (f a) -> Sem (WithTactics e f m r) (f (Either err a))
distribEither = \case
  Right f a
fa ->
    f (Either err a) -> Sem (WithTactics e f m r) (f (Either err a))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> Either err a
forall a b. b -> Either a b
Right (a -> Either err a) -> f a -> f (Either err a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f a
fa)
  Left err
err -> do
    f ()
s <- Sem (WithTactics e f m r) (f ())
forall (f :: * -> *) (m :: * -> *) (r :: EffectRow)
       (e :: (* -> *) -> * -> *).
Sem (WithTactics e f m r) (f ())
getInitialStateT
    pure (err -> Either err a
forall a b. a -> Either a b
Left err
err Either err a -> f () -> f (Either err a)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f ()
s)
{-# inline distribEither #-}

-- |Same as 'interpretHttpNative', but the interpretation of 'Manager' is left to the user.
interpretHttpNativeWith ::
  Members [Embed IO, Log, Resource, Manager] r =>
  InterpreterFor (Http BodyReader) r
interpretHttpNativeWith :: forall (r :: EffectRow).
Members '[Embed IO, Log, Resource, Manager] r =>
InterpreterFor (Http BodyReader) r
interpretHttpNativeWith =
  (forall (rInitial :: EffectRow) x.
 Http BodyReader (Sem rInitial) x
 -> Tactical (Http BodyReader) (Sem rInitial) r x)
-> Sem (Http BodyReader : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
(forall (rInitial :: EffectRow) x.
 e (Sem rInitial) x -> Tactical e (Sem rInitial) r x)
-> Sem (e : r) a -> Sem r a
interpretH \case
    Http.Response Request
request Response BodyReader -> Sem rInitial a1
f ->
      Either HttpError (f a1)
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError a1))
forall (f :: * -> *) err a (e :: (* -> *) -> * -> *) (m :: * -> *)
       (r :: EffectRow).
Functor f =>
Either err (f a) -> Sem (WithTactics e f m r) (f (Either err a))
distribEither (Either HttpError (f a1)
 -> Sem
      (WithTactics (Http BodyReader) f (Sem rInitial) r)
      (f (Either HttpError a1)))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (Either HttpError (f a1))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError a1))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Request
-> (Response BodyReader
    -> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) (f a1))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (Either HttpError (f a1))
forall (r :: EffectRow) a.
Members '[Embed IO, Log, Resource, Manager] r =>
Request
-> (Response BodyReader -> Sem r a) -> Sem r (Either HttpError a)
withResponse Request
request ((\ Sem rInitial a1
x -> Sem rInitial a1 -> Tactical (Http BodyReader) (Sem rInitial) r a1
forall (m :: * -> *) a (e :: (* -> *) -> * -> *) (r :: EffectRow).
m a -> Tactical e m r a
runTSimple Sem rInitial a1
x) (Sem rInitial a1
 -> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) (f a1))
-> (Response BodyReader -> Sem rInitial a1)
-> Response BodyReader
-> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) (f a1)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response BodyReader -> Sem rInitial a1
f)
    Http.Request Request
request -> do
      Text -> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) ()
forall (r :: EffectRow).
(HasCallStack, Member Log r) =>
Text -> Sem r ()
Log.debug [exon|http request: #{show request}|]
      Manager
manager <- Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) Manager
forall (r :: EffectRow). Member Manager r => Sem r Manager
Manager.get
      Sem r (Either HttpError (Response LByteString))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError (Response LByteString)))
forall (m :: * -> *) (f :: * -> *) (r :: EffectRow)
       (e :: (* -> *) -> * -> *) a.
Functor f =>
Sem r a -> Sem (WithTactics e f m r) (f a)
liftT do
        Either HttpError (Response LByteString)
response <- Manager
-> Request -> Sem r (Either HttpError (Response LByteString))
forall (r :: EffectRow).
Member (Embed IO) r =>
Manager
-> Request -> Sem r (Either HttpError (Response LByteString))
executeRequest Manager
manager Request
request
        Either HttpError (Response LByteString)
response Either HttpError (Response LByteString)
-> Sem r () -> Sem r (Either HttpError (Response LByteString))
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member Log r) =>
Text -> Sem r ()
Log.debug [exon|http response: #{show response}|]
    Http.Stream Request
request Response BodyReader -> Sem rInitial a1
handler -> do
      Text -> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) ()
forall (r :: EffectRow).
(HasCallStack, Member Log r) =>
Text -> Sem r ()
Log.debug [exon|http stream request: #{show request}|]
      Either HttpError (f a1)
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError a1))
forall (f :: * -> *) err a (e :: (* -> *) -> * -> *) (m :: * -> *)
       (r :: EffectRow).
Functor f =>
Either err (f a) -> Sem (WithTactics e f m r) (f (Either err a))
distribEither (Either HttpError (f a1)
 -> Sem
      (WithTactics (Http BodyReader) f (Sem rInitial) r)
      (f (Either HttpError a1)))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (Either HttpError (f a1))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError a1))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Request
-> (Response BodyReader
    -> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) (f a1))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (Either HttpError (f a1))
forall (r :: EffectRow) a.
Members '[Embed IO, Log, Resource, Manager] r =>
Request
-> (Response BodyReader -> Sem r a) -> Sem r (Either HttpError a)
withResponse Request
request ((\ Sem rInitial a1
x -> Sem rInitial a1 -> Tactical (Http BodyReader) (Sem rInitial) r a1
forall (m :: * -> *) a (e :: (* -> *) -> * -> *) (r :: EffectRow).
m a -> Tactical e m r a
runTSimple Sem rInitial a1
x) (Sem rInitial a1
 -> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) (f a1))
-> (Response BodyReader -> Sem rInitial a1)
-> Response BodyReader
-> Sem (WithTactics (Http BodyReader) f (Sem rInitial) r) (f a1)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response BodyReader -> Sem rInitial a1
handler)
    Http.ConsumeChunk BodyReader
body ->
      Either HttpError ByteString
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError ByteString))
forall (f :: * -> *) a (e :: (* -> *) -> * -> *) (m :: * -> *)
       (r :: EffectRow).
Functor f =>
a -> Sem (WithTactics e f m r) (f a)
pureT (Either HttpError ByteString
 -> Sem
      (WithTactics (Http BodyReader) f (Sem rInitial) r)
      (f (Either HttpError ByteString)))
-> (Either Text ByteString -> Either HttpError ByteString)
-> Either Text ByteString
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> HttpError)
-> Either Text ByteString -> Either HttpError ByteString
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Text -> HttpError
HttpError.ChunkFailed (Either Text ByteString
 -> Sem
      (WithTactics (Http BodyReader) f (Sem rInitial) r)
      (f (Either HttpError ByteString)))
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (Either Text ByteString)
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (f (Either HttpError ByteString))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BodyReader
-> Sem
     (WithTactics (Http BodyReader) f (Sem rInitial) r)
     (Either Text ByteString)
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either Text a)
tryAny BodyReader
body
{-# inline interpretHttpNativeWith #-}

-- |Interpret @'Http' 'BodyReader'@ using the native "Network.HTTP.Client" implementation.
-- 'BodyReader' is an alias for @'IO' 'ByteString'@; it is how http-client represents chunks.
-- This uses the default interpreter for 'Manager'.
interpretHttpNative ::
  Members [Embed IO, Log, Resource] r =>
  InterpreterFor (Http BodyReader) r
interpretHttpNative :: forall (r :: EffectRow).
Members '[Embed IO, Log, Resource] r =>
InterpreterFor (Http BodyReader) r
interpretHttpNative =
  Sem (Manager : r) a -> Sem r a
forall (r :: EffectRow).
Member (Embed IO) r =>
InterpreterFor Manager r
interpretManager (Sem (Manager : r) a -> Sem r a)
-> (Sem (Http BodyReader : r) a -> Sem (Manager : r) a)
-> Sem (Http BodyReader : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (Http BodyReader : Manager : r) a -> Sem (Manager : r) a
forall (r :: EffectRow).
Members '[Embed IO, Log, Resource, Manager] r =>
InterpreterFor (Http BodyReader) r
interpretHttpNativeWith (Sem (Http BodyReader : Manager : r) a -> Sem (Manager : r) a)
-> (Sem (Http BodyReader : r) a
    -> Sem (Http BodyReader : Manager : r) a)
-> Sem (Http BodyReader : r) a
-> Sem (Manager : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (Http BodyReader : r) a
-> Sem (Http BodyReader : Manager : r) a
forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *)
       (r :: EffectRow) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder
{-# inline interpretHttpNative #-}