{-# LANGUAGE NoImplicitPrelude #-}

module Network.HTTP.Client.Context
  ( -- * Updating manager settings
    modifyRequestsWithContext
  , modifyResponsesWithContext
  ) where

import Network.HTTP.Client (BodyReader, ManagerSettings, Request, Response)
import Prelude
import qualified Context
import qualified Network.HTTP.Client as HTTP.Client

-- | Update the provided 'ManagerSettings' to modify all outgoing 'Request'
-- values, utilizing the calling thread's registered context if present.
--
-- Note that the modifying function can be called multiple times, so be sure to
-- define your function to first check if the 'Request' needs modification. See
-- 'HTTP.Client.managerModifyRequest' for details.
--
-- @since 0.1.0.0
modifyRequestsWithContext
  :: Context.Store ctx
  -> (Maybe ctx -> Request -> IO Request)
  -> ManagerSettings
  -> ManagerSettings
modifyRequestsWithContext :: Store ctx
-> (Maybe ctx -> Request -> IO Request)
-> ManagerSettings
-> ManagerSettings
modifyRequestsWithContext Store ctx
contextStore Maybe ctx -> Request -> IO Request
updateRequest ManagerSettings
managerSettings =
  ManagerSettings
managerSettings
    { managerModifyRequest :: Request -> IO Request
HTTP.Client.managerModifyRequest = \Request
initRequest -> do
        -- In case the provided manager settings already had a custom
        -- request-modifying action installed, we make sure to run that on the
        -- request so that we do not miss its modifications.
        Request
request <- Request -> IO Request
originalRequestModifier Request
initRequest

        Maybe ctx
mContext <- Store ctx -> IO (Maybe ctx)
forall (m :: * -> *) ctx. MonadIO m => Store ctx -> m (Maybe ctx)
Context.mineMay Store ctx
contextStore
        Maybe ctx -> Request -> IO Request
updateRequest Maybe ctx
mContext Request
request
    }
  where
    originalRequestModifier :: Request -> IO Request
originalRequestModifier = ManagerSettings -> Request -> IO Request
HTTP.Client.managerModifyRequest ManagerSettings
managerSettings

-- | Update the provided 'ManagerSettings' to modify all incoming 'Response'
-- values, utilizing the calling thread's registered context if present.
--
-- @since 0.1.0.0
modifyResponsesWithContext
  :: Context.Store ctx
  -> (Maybe ctx -> Response BodyReader -> IO (Response BodyReader))
  -> ManagerSettings
  -> ManagerSettings
modifyResponsesWithContext :: Store ctx
-> (Maybe ctx -> Response BodyReader -> IO (Response BodyReader))
-> ManagerSettings
-> ManagerSettings
modifyResponsesWithContext Store ctx
contextStore Maybe ctx -> Response BodyReader -> IO (Response BodyReader)
updateResponse ManagerSettings
managerSettings =
  ManagerSettings
managerSettings
    { managerModifyResponse :: Response BodyReader -> IO (Response BodyReader)
HTTP.Client.managerModifyResponse = \Response BodyReader
initResponse -> do
        -- In case the provided manager settings already had a custom
        -- response-modifying action installed, we make sure to run that on the
        -- response so that we do not miss its modifications.
        Response BodyReader
response <- Response BodyReader -> IO (Response BodyReader)
originalResponseModifier Response BodyReader
initResponse

        Maybe ctx
mContext <- Store ctx -> IO (Maybe ctx)
forall (m :: * -> *) ctx. MonadIO m => Store ctx -> m (Maybe ctx)
Context.mineMay Store ctx
contextStore
        Maybe ctx -> Response BodyReader -> IO (Response BodyReader)
updateResponse Maybe ctx
mContext Response BodyReader
response
    }
  where
    originalResponseModifier :: Response BodyReader -> IO (Response BodyReader)
originalResponseModifier = ManagerSettings -> Response BodyReader -> IO (Response BodyReader)
HTTP.Client.managerModifyResponse ManagerSettings
managerSettings