Delete catchbevior and allow a user to provide a catch.
By default the one from unliftIO is used.
This commit is contained in:
parent
d04c22e3d6
commit
5ac65db1bf
@ -1,23 +0,0 @@
|
|||||||
{-# LANGUAGE LambdaCase #-}
|
|
||||||
|
|
||||||
-- | module providing an abstract type around 'CatchBehavior'
|
|
||||||
-- through smart constructors.
|
|
||||||
-- providing future additional extensibility.
|
|
||||||
--
|
|
||||||
-- @since 1.6.24.0
|
|
||||||
module Yesod.Core.CatchBehavior(CatchBehavior, rethrow, catch, isCatch) where
|
|
||||||
|
|
||||||
-- | @since 1.6.24.0
|
|
||||||
data CatchBehavior = Rethrow -- ^ Rethrow an exception and let the webserver deal with it (usually warp)
|
|
||||||
| Catch -- ^ catch an exception and render in yesod
|
|
||||||
|
|
||||||
rethrow :: CatchBehavior
|
|
||||||
rethrow = Rethrow
|
|
||||||
|
|
||||||
catch :: CatchBehavior
|
|
||||||
catch = Catch
|
|
||||||
|
|
||||||
isCatch :: CatchBehavior -> Bool
|
|
||||||
isCatch = \case
|
|
||||||
Catch -> True
|
|
||||||
Rethrow -> False
|
|
||||||
@ -57,10 +57,7 @@ import Data.CaseInsensitive (CI)
|
|||||||
import qualified Network.Wai.Handler.Warp as Warp
|
import qualified Network.Wai.Handler.Warp as Warp
|
||||||
import qualified Network.Wai.Request
|
import qualified Network.Wai.Request
|
||||||
import Data.IORef
|
import Data.IORef
|
||||||
import UnliftIO (SomeException, fromException, isSyncException, fromExceptionUnwrap)
|
import UnliftIO (SomeException, catch)
|
||||||
import Data.Proxy(Proxy)
|
|
||||||
import Yesod.Core.CatchBehavior
|
|
||||||
import System.Timeout(Timeout)
|
|
||||||
|
|
||||||
-- | Define settings for a Yesod applications. All methods have intelligent
|
-- | Define settings for a Yesod applications. All methods have intelligent
|
||||||
-- defaults, and therefore no implementation is required.
|
-- defaults, and therefore no implementation is required.
|
||||||
@ -84,8 +81,8 @@ class RenderRoute site => Yesod site where
|
|||||||
-- catching allows yesod to render the error page.
|
-- catching allows yesod to render the error page.
|
||||||
-- the default 'rethrowAsync' is to rethrow async
|
-- the default 'rethrowAsync' is to rethrow async
|
||||||
-- exceptions.
|
-- exceptions.
|
||||||
catchBehavior :: site -> SomeException -> IO CatchBehavior
|
catchBehavior :: site -> IO a -> (SomeException -> IO a) -> IO a
|
||||||
catchBehavior _ = pure . rethrowAsync
|
catchBehavior _ = catch
|
||||||
|
|
||||||
-- | Output error response pages.
|
-- | Output error response pages.
|
||||||
--
|
--
|
||||||
@ -651,10 +648,6 @@ widgetToPageContent w = do
|
|||||||
runUniqueList :: Eq x => UniqueList x -> [x]
|
runUniqueList :: Eq x => UniqueList x -> [x]
|
||||||
runUniqueList (UniqueList x) = nub $ x []
|
runUniqueList (UniqueList x) = nub $ x []
|
||||||
|
|
||||||
rethrowAsync :: SomeException -> CatchBehavior
|
|
||||||
rethrowAsync exception =
|
|
||||||
if isSyncException exception then catch else rethrow
|
|
||||||
|
|
||||||
-- | The default error handler for 'errorHandler'.
|
-- | The default error handler for 'errorHandler'.
|
||||||
defaultErrorHandler :: Yesod site => ErrorResponse -> HandlerFor site TypedContent
|
defaultErrorHandler :: Yesod site => ErrorResponse -> HandlerFor site TypedContent
|
||||||
defaultErrorHandler NotFound = selectRep $ do
|
defaultErrorHandler NotFound = selectRep $ do
|
||||||
|
|||||||
@ -56,27 +56,17 @@ import Control.DeepSeq (($!!), NFData)
|
|||||||
import UnliftIO.Exception
|
import UnliftIO.Exception
|
||||||
import UnliftIO(MonadUnliftIO, withRunInIO)
|
import UnliftIO(MonadUnliftIO, withRunInIO)
|
||||||
import Data.Proxy(Proxy(..))
|
import Data.Proxy(Proxy(..))
|
||||||
import Yesod.Core.CatchBehavior
|
|
||||||
|
|
||||||
-- | like `catch` but doesn't check for async exceptions,
|
-- | wraps the provided catch fun in a unliftIO
|
||||||
-- thereby catching them too.
|
|
||||||
-- This is desirable for letting yesod generate a 500 error page
|
|
||||||
-- rather then warp.
|
|
||||||
--
|
|
||||||
-- Normally this is VERY dubious. you need to rethrow.
|
|
||||||
-- recovrery from async isn't allowed.
|
|
||||||
-- see async section: https://www.fpcomplete.com/blog/2018/04/async-exception-handling-haskell/
|
|
||||||
unsafeAsyncCatch
|
unsafeAsyncCatch
|
||||||
:: (MonadUnliftIO m)
|
:: (MonadUnliftIO m)
|
||||||
=> (SomeException -> IO CatchBehavior)
|
=> (IO a -> (SomeException -> IO a) -> IO a)
|
||||||
-> m a -- ^ action
|
-> m a -- ^ action
|
||||||
-> (SomeException -> m a) -- ^ handler
|
-> (SomeException -> m a) -- ^ handler
|
||||||
-> m a
|
-> m a
|
||||||
unsafeAsyncCatch catchBehavior f g = withRunInIO $ \run -> run f `EUnsafe.catch` \e -> do
|
unsafeAsyncCatch catchFun f g = withRunInIO $ \run ->
|
||||||
caught <- liftIO $ catchBehavior e
|
run f `catchFun` \e -> run (g e)
|
||||||
if isCatch caught
|
|
||||||
then run (g e)
|
|
||||||
else liftIO $ EUnsafe.throwIO e
|
|
||||||
|
|
||||||
-- | Convert a synchronous exception into an ErrorResponse
|
-- | Convert a synchronous exception into an ErrorResponse
|
||||||
toErrorHandler :: SomeException -> IO ErrorResponse
|
toErrorHandler :: SomeException -> IO ErrorResponse
|
||||||
@ -213,7 +203,7 @@ handleContents handleError' finalSession headers contents =
|
|||||||
--
|
--
|
||||||
-- Note that this also catches async exceptions.
|
-- Note that this also catches async exceptions.
|
||||||
evalFallback :: (Monoid w, NFData w)
|
evalFallback :: (Monoid w, NFData w)
|
||||||
=> (SomeException -> IO CatchBehavior)
|
=> (forall a. IO a -> (SomeException -> IO a) -> IO a)
|
||||||
-> HandlerContents
|
-> HandlerContents
|
||||||
-> w
|
-> w
|
||||||
-> IO (w, HandlerContents)
|
-> IO (w, HandlerContents)
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
{-# LANGUAGE GADTs #-}
|
{-# LANGUAGE GADTs #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
module Yesod.Core.Types where
|
module Yesod.Core.Types where
|
||||||
|
|
||||||
import Data.Aeson (ToJSON)
|
import Data.Aeson (ToJSON)
|
||||||
@ -56,7 +57,6 @@ import Control.DeepSeq (NFData (rnf))
|
|||||||
import Yesod.Core.TypeCache (TypeMap, KeyedTypeMap)
|
import Yesod.Core.TypeCache (TypeMap, KeyedTypeMap)
|
||||||
import Control.Monad.Logger (MonadLoggerIO (..))
|
import Control.Monad.Logger (MonadLoggerIO (..))
|
||||||
import UnliftIO (MonadUnliftIO (..), SomeException)
|
import UnliftIO (MonadUnliftIO (..), SomeException)
|
||||||
import Yesod.Core.CatchBehavior
|
|
||||||
|
|
||||||
-- Sessions
|
-- Sessions
|
||||||
type SessionMap = Map Text ByteString
|
type SessionMap = Map Text ByteString
|
||||||
@ -186,7 +186,7 @@ data RunHandlerEnv child site = RunHandlerEnv
|
|||||||
|
|
||||||
-- | @since 1.6.24.0
|
-- | @since 1.6.24.0
|
||||||
-- should we catch an exception, or rethrow it.
|
-- should we catch an exception, or rethrow it.
|
||||||
, rheShouldCatch :: !(SomeException -> IO CatchBehavior)
|
, rheShouldCatch :: !(forall a. IO a -> (SomeException -> IO a) -> IO a)
|
||||||
}
|
}
|
||||||
|
|
||||||
data HandlerData child site = HandlerData
|
data HandlerData child site = HandlerData
|
||||||
|
|||||||
@ -15,7 +15,6 @@ module YesodCoreTest.ErrorHandling.CustomApp
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
|
|
||||||
import Yesod.Core.CatchBehavior
|
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import qualified UnliftIO.Exception as E
|
import qualified UnliftIO.Exception as E
|
||||||
@ -34,7 +33,9 @@ data MyException = MkMyException
|
|||||||
deriving (Show, E.Exception)
|
deriving (Show, E.Exception)
|
||||||
|
|
||||||
instance Yesod CustomApp where
|
instance Yesod CustomApp where
|
||||||
catchBehavior _ exception = pure $
|
-- something we couldn't do before, rethrow custom exceptions
|
||||||
case E.fromException exception of
|
catchBehavior _ action handler =
|
||||||
Just MkMyException -> rethrow
|
action `E.catch` \exception -> do
|
||||||
Nothing -> catch
|
case E.fromException exception of
|
||||||
|
Just MkMyException -> E.throwIO MkMyException
|
||||||
|
Nothing -> handler exception
|
||||||
|
|||||||
@ -75,7 +75,6 @@ library
|
|||||||
Yesod.Core.Types
|
Yesod.Core.Types
|
||||||
Yesod.Core.Unsafe
|
Yesod.Core.Unsafe
|
||||||
Yesod.Routes.TH.Types
|
Yesod.Routes.TH.Types
|
||||||
Yesod.Core.CatchBehavior
|
|
||||||
other-modules: Yesod.Core.Internal.Session
|
other-modules: Yesod.Core.Internal.Session
|
||||||
Yesod.Core.Internal.Request
|
Yesod.Core.Internal.Request
|
||||||
Yesod.Core.Class.Handler
|
Yesod.Core.Class.Handler
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user