salvia-1.0.0: src/Network/Salvia/Handler/Error.hs
{-# LANGUAGE FlexibleContexts #-}
module Network.Salvia.Handler.Error
( hError
, hCustomError
, hIOError
, hSafeIO
, catchIO
)
where
import Control.Monad.Trans
import Data.Record.Label
import Network.Protocol.Http
import Network.Salvia.Interface
import System.IO.Error
-- | The 'hError' handler enables the creation of a default style of error
-- responses for the specified HTTP `Status` code.
hError :: (HttpM Response m, SendM m) => Status -> m ()
hError e = hCustomError e
(concat ["[", show (codeFromStatus e), "] ", show e, "\n"])
-- | Like `hError` but with a custom error message.
hCustomError :: (HttpM Response m, SendM m) => Status -> String -> m ()
hCustomError e m =
do response $
do status =: e
contentLength =: Just (length m)
contentType =: Just ("text/plain", Nothing)
send m
{- |
Map an `IOError` to a default style error response.
The mapping from an IO error to an error response is rather straightforward:
> | isDoesNotExistError e = hError NotFound
> | isAlreadyInUseError e = hError ServiceUnavailable
> | isPermissionError e = hError Forbidden
> | True = hError InternalServerError
-}
hIOError :: (HttpM Response m, SendM m) => IOError -> m ()
hIOError e
| isDoesNotExistError e = hError NotFound
| isAlreadyInUseError e = hError ServiceUnavailable
| isPermissionError e = hError Forbidden
| otherwise = hError InternalServerError
-- | Execute an handler with the result of an IO action. When the IO actions
-- fails a default error handler will be executed.
hSafeIO
:: (MonadIO m, HttpM Response m, SendM m)
=> IO a -> (a -> m ()) -> m ()
hSafeIO io h = liftIO (try io) >>= either hIOError h
-- | Utility function to easily catch IO errors.
catchIO :: MonadIO m => IO a -> a -> m a
catchIO a b = liftIO (a `catch` (const (return b)))