module Ecluse.Core.Registry.Exchange (
boundedFetch,
boundedRelay,
) where
import Data.ByteString.Lazy qualified as LBS
import Network.HTTP.Client (
BodyReader,
Manager,
Request,
Response (responseStatus),
brRead,
responseBody,
withResponse,
)
import Network.HTTP.Types.Status (statusCode)
import UnliftIO (try)
import Ecluse.Core.Fault.Http (classifyTransport)
import Ecluse.Core.Registry (
FetchFault (FetchBoundExceeded, FetchTransport),
PublishRelayFault (RelayBoundExceeded, RelayTransport),
PublishRelayResponse (..),
RegistryResponse (RegistryResponse),
)
import Ecluse.Core.Security (LimitError, Limits, boundedRead)
boundedFetch :: Manager -> Limits -> Request -> IO (Either FetchFault RegistryResponse)
boundedFetch :: Manager
-> Limits -> Request -> IO (Either FetchFault RegistryResponse)
boundedFetch Manager
manager Limits
limits Request
request =
IO (Either LimitError RegistryResponse)
-> IO (Either HttpException (Either LimitError RegistryResponse))
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try (Request
-> Manager
-> (Response BodyReader -> IO (Either LimitError RegistryResponse))
-> IO (Either LimitError RegistryResponse)
forall a.
Request -> Manager -> (Response BodyReader -> IO a) -> IO a
withResponse Request
request Manager
manager (Limits -> BodyReader -> IO (Either LimitError RegistryResponse)
readBoundedBody Limits
limits (BodyReader -> IO (Either LimitError RegistryResponse))
-> (Response BodyReader -> BodyReader)
-> Response BodyReader
-> IO (Either LimitError RegistryResponse)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response BodyReader -> BodyReader
forall body. Response body -> body
responseBody))
IO (Either HttpException (Either LimitError RegistryResponse))
-> (Either HttpException (Either LimitError RegistryResponse)
-> Either FetchFault RegistryResponse)
-> IO (Either FetchFault RegistryResponse)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Left HttpException
httpErr -> FetchFault -> Either FetchFault RegistryResponse
forall a b. a -> Either a b
Left (TransportFault -> FetchFault
FetchTransport (HttpException -> TransportFault
classifyTransport HttpException
httpErr))
Right (Left LimitError
limitErr) -> FetchFault -> Either FetchFault RegistryResponse
forall a b. a -> Either a b
Left (LimitError -> FetchFault
FetchBoundExceeded LimitError
limitErr)
Right (Right RegistryResponse
response) -> RegistryResponse -> Either FetchFault RegistryResponse
forall a b. b -> Either a b
Right RegistryResponse
response
boundedRelay :: Manager -> Limits -> Request -> IO (Either PublishRelayFault PublishRelayResponse)
boundedRelay :: Manager
-> Limits
-> Request
-> IO (Either PublishRelayFault PublishRelayResponse)
boundedRelay Manager
manager Limits
limits Request
request =
IO (Either PublishRelayFault PublishRelayResponse)
-> IO
(Either
HttpException (Either PublishRelayFault PublishRelayResponse))
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try (Request
-> Manager
-> (Response BodyReader
-> IO (Either PublishRelayFault PublishRelayResponse))
-> IO (Either PublishRelayFault PublishRelayResponse)
forall a.
Request -> Manager -> (Response BodyReader -> IO a) -> IO a
withResponse Request
request Manager
manager (Limits
-> Response BodyReader
-> IO (Either PublishRelayFault PublishRelayResponse)
readRelayResponse Limits
limits))
IO
(Either
HttpException (Either PublishRelayFault PublishRelayResponse))
-> (Either
HttpException (Either PublishRelayFault PublishRelayResponse)
-> Either PublishRelayFault PublishRelayResponse)
-> IO (Either PublishRelayFault PublishRelayResponse)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Left HttpException
httpErr -> PublishRelayFault -> Either PublishRelayFault PublishRelayResponse
forall a b. a -> Either a b
Left (TransportFault -> PublishRelayFault
RelayTransport (HttpException -> TransportFault
classifyTransport HttpException
httpErr))
Right Either PublishRelayFault PublishRelayResponse
relayed -> Either PublishRelayFault PublishRelayResponse
relayed
readBoundedBody :: Limits -> BodyReader -> IO (Either LimitError RegistryResponse)
readBoundedBody :: Limits -> BodyReader -> IO (Either LimitError RegistryResponse)
readBoundedBody Limits
limits BodyReader
bodyReader =
(ByteString -> RegistryResponse)
-> Either LimitError ByteString
-> Either LimitError RegistryResponse
forall a b. (a -> b) -> Either LimitError a -> Either LimitError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> RegistryResponse
RegistryResponse (Either LimitError ByteString
-> Either LimitError RegistryResponse)
-> IO (Either LimitError ByteString)
-> IO (Either LimitError RegistryResponse)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Limits -> BodyReader -> IO (Either LimitError ByteString)
forall (m :: * -> *).
Monad m =>
Limits -> m ByteString -> m (Either LimitError ByteString)
boundedRead Limits
limits (BodyReader -> BodyReader
brRead BodyReader
bodyReader)
readRelayResponse :: Limits -> Response BodyReader -> IO (Either PublishRelayFault PublishRelayResponse)
readRelayResponse :: Limits
-> Response BodyReader
-> IO (Either PublishRelayFault PublishRelayResponse)
readRelayResponse Limits
limits Response BodyReader
response =
Limits -> BodyReader -> IO (Either LimitError RegistryResponse)
readBoundedBody Limits
limits (Response BodyReader -> BodyReader
forall body. Response body -> body
responseBody Response BodyReader
response) IO (Either LimitError RegistryResponse)
-> (Either LimitError RegistryResponse
-> Either PublishRelayFault PublishRelayResponse)
-> IO (Either PublishRelayFault PublishRelayResponse)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Left LimitError
limitErr -> PublishRelayFault -> Either PublishRelayFault PublishRelayResponse
forall a b. a -> Either a b
Left (LimitError -> PublishRelayFault
RelayBoundExceeded LimitError
limitErr)
Right (RegistryResponse ByteString
body) ->
PublishRelayResponse
-> Either PublishRelayFault PublishRelayResponse
forall a b. b -> Either a b
Right
PublishRelayResponse
{ relayStatus :: Int
relayStatus = Status -> Int
statusCode (Response BodyReader -> Status
forall body. Response body -> Status
responseStatus Response BodyReader
response)
, relayBody :: LByteString
relayBody = ByteString -> LByteString
LBS.fromStrict ByteString
body
}