-- | Definition of 'RequestHandler'
--
-- Defined in a separate module to avoid cyclic module dependencies.
--
-- Intended for unqualified import.
module Network.GRPC.Server.RequestHandler.API (
    RequestHandler
  , requestHandlerToServer
  ) where

import Control.Exception

import Network.HTTP2.Server qualified as HTTP2

{-------------------------------------------------------------------------------
  Definition
-------------------------------------------------------------------------------}

-- | HTTP2 request handler
type RequestHandler a =
     (forall x. IO x -> IO x)
  -> HTTP2.Request
  -> (HTTP2.Response -> IO ())
  -> IO a

-- | Construct @http2@ handler
requestHandlerToServer ::
     RequestHandler ()
     -- ^ Request handler
     --
     -- We can assume in 'requestHandlerToServer' that the handler will not
     -- throw any exceptions (doing so will cause @http2@ to reset the stream,
     -- which is not always the right thing to do; see detailed comments in
     -- 'runHandler'). It is the responsibility of 'serverTopLevel' (prior to
     -- calling 'requestHandlerToServer') to catch any remaining exceptions.
  -> HTTP2.Server
requestHandlerToServer :: RequestHandler () -> Server
requestHandlerToServer RequestHandler ()
handler Request
req Aux
_aux Response -> [PushPromise] -> IO ()
respond =
    -- We start by masking asynchronous exceptions. It is possible that
    -- http2 kills us /before/ this call to @mask@, but if it does, no harm
    -- is done: nothing has happened yet, so nothing is interrupted.
    ((forall a. IO a -> IO a) -> IO ()) -> IO ()
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask (((forall a. IO a -> IO a) -> IO ()) -> IO ())
-> ((forall a. IO a -> IO a) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
unmask ->
      RequestHandler ()
handler IO x -> IO x
forall a. IO a -> IO a
unmask Request
req (\Response
resp -> Response -> [PushPromise] -> IO ()
respond Response
resp [])