add a field in Delayed that lets us specify a clean up action that can use the result of bodyD to perform some IO clean up operation
This commit is contained in:
parent
cce0f59ec8
commit
124c6de1eb
2 changed files with 30 additions and 13 deletions
|
@ -400,7 +400,7 @@ instance HasServer Raw context where
|
||||||
type ServerT Raw m = Application
|
type ServerT Raw m = Application
|
||||||
|
|
||||||
route Proxy _ rawApplication = RawRouter $ \ env request respond -> do
|
route Proxy _ rawApplication = RawRouter $ \ env request respond -> do
|
||||||
r <- runDelayed rawApplication env request
|
(r, _) <- runDelayed rawApplication env request
|
||||||
case r of
|
case r of
|
||||||
Route app -> app request (respond . Route)
|
Route app -> app request (respond . Route)
|
||||||
Fail a -> respond $ Fail a
|
Fail a -> respond $ Fail a
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
{-# LANGUAGE KindSignatures #-}
|
{-# LANGUAGE KindSignatures #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE StandaloneDeriving #-}
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
module Servant.Server.Internal.RoutingApplication where
|
module Servant.Server.Internal.RoutingApplication where
|
||||||
|
|
||||||
import Control.Monad (ap, liftM)
|
import Control.Monad (ap, liftM)
|
||||||
import Control.Monad.Trans (MonadIO(..))
|
import Control.Monad.Trans (MonadIO(..))
|
||||||
|
import Control.Monad.Trans.Except (runExceptT)
|
||||||
|
import Data.IORef (newIORef, readIORef, writeIORef)
|
||||||
import Network.Wai (Application, Request,
|
import Network.Wai (Application, Request,
|
||||||
Response, ResponseReceived)
|
Response, ResponseReceived)
|
||||||
import Prelude ()
|
import Prelude ()
|
||||||
|
@ -103,6 +106,10 @@ data Delayed env c where
|
||||||
, authD :: DelayedIO auth
|
, authD :: DelayedIO auth
|
||||||
, bodyD :: DelayedIO body
|
, bodyD :: DelayedIO body
|
||||||
, serverD :: captures -> auth -> body -> Request -> RouteResult c
|
, serverD :: captures -> auth -> body -> Request -> RouteResult c
|
||||||
|
, cleanupD :: body -> IO ()
|
||||||
|
-- not in DelayedIO because:
|
||||||
|
-- - most likely should not depend on the request
|
||||||
|
-- - simpler
|
||||||
} -> Delayed env c
|
} -> Delayed env c
|
||||||
|
|
||||||
instance Functor (Delayed env) where
|
instance Functor (Delayed env) where
|
||||||
|
@ -142,7 +149,7 @@ instance MonadIO DelayedIO where
|
||||||
-- | A 'Delayed' without any stored checks.
|
-- | A 'Delayed' without any stored checks.
|
||||||
emptyDelayed :: RouteResult a -> Delayed env a
|
emptyDelayed :: RouteResult a -> Delayed env a
|
||||||
emptyDelayed result =
|
emptyDelayed result =
|
||||||
Delayed (const r) r r r (\ _ _ _ _ -> result)
|
Delayed (const r) r r r (\ _ _ _ _ -> result) (const $ return ())
|
||||||
where
|
where
|
||||||
r = return ()
|
r = return ()
|
||||||
|
|
||||||
|
@ -198,6 +205,7 @@ addBodyCheck Delayed{..} new =
|
||||||
Delayed
|
Delayed
|
||||||
{ bodyD = (,) <$> bodyD <*> new
|
{ bodyD = (,) <$> bodyD <*> new
|
||||||
, serverD = \ c a (z, v) req -> ($ v) <$> serverD c a z req
|
, serverD = \ c a (z, v) req -> ($ v) <$> serverD c a z req
|
||||||
|
, cleanupD = cleanupD . fst -- not sure that's right
|
||||||
, ..
|
, ..
|
||||||
} -- Note [Existential Record Update]
|
} -- Note [Existential Record Update]
|
||||||
|
|
||||||
|
@ -240,13 +248,19 @@ passToServer Delayed{..} x =
|
||||||
runDelayed :: Delayed env a
|
runDelayed :: Delayed env a
|
||||||
-> env
|
-> env
|
||||||
-> Request
|
-> Request
|
||||||
-> IO (RouteResult a)
|
-> IO (RouteResult a, IO ())
|
||||||
runDelayed Delayed{..} env = runDelayedIO $ do
|
runDelayed Delayed{..} env req = do
|
||||||
c <- capturesD env
|
cleanupRef <- newIORef (return ())
|
||||||
|
routeRes <- runDelayedIO
|
||||||
|
(do c <- capturesD env
|
||||||
methodD
|
methodD
|
||||||
a <- authD
|
a <- authD
|
||||||
b <- bodyD
|
b <- bodyD
|
||||||
DelayedIO (\ req -> return $ serverD c a b req)
|
liftIO (writeIORef cleanupRef $ cleanupD b)
|
||||||
|
DelayedIO $ \ req -> return (serverD c a b req)
|
||||||
|
)
|
||||||
|
req
|
||||||
|
fmap (routeRes,) $ readIORef cleanupRef
|
||||||
|
|
||||||
-- | Runs a delayed server and the resulting action.
|
-- | Runs a delayed server and the resulting action.
|
||||||
-- Takes a continuation that lets us send a response.
|
-- Takes a continuation that lets us send a response.
|
||||||
|
@ -258,8 +272,11 @@ runAction :: Delayed env (Handler a)
|
||||||
-> (RouteResult Response -> IO r)
|
-> (RouteResult Response -> IO r)
|
||||||
-> (a -> RouteResult Response)
|
-> (a -> RouteResult Response)
|
||||||
-> IO r
|
-> IO r
|
||||||
runAction action env req respond k =
|
runAction action env req respond k = do
|
||||||
runDelayed action env req >>= go >>= respond
|
(routeResult, cleanup) <- runDelayed action env req
|
||||||
|
resp <- go routeResult
|
||||||
|
cleanup
|
||||||
|
respond resp
|
||||||
where
|
where
|
||||||
go (Fail e) = return $ Fail e
|
go (Fail e) = return $ Fail e
|
||||||
go (FailFatal e) = return $ FailFatal e
|
go (FailFatal e) = return $ FailFatal e
|
||||||
|
|
Loading…
Reference in a new issue