HTML for ServerError; drop mock database effect handler

This commit is contained in:
James Eversole 2024-10-22 18:55:15 -05:00
parent 3f76917c40
commit 13e8a11e83
7 changed files with 41 additions and 51 deletions

View File

@ -60,6 +60,7 @@ executable Main
Handlers Handlers
Logger Logger
Routes Routes
Utility
Views Views
build-depends: build-depends:
HELPS HELPS
@ -68,4 +69,4 @@ library
import: global import: global
hs-source-dirs: hs-source-dirs:
src src
exposed-modules: Core, Database, Handlers, Logger, Routes, Views, Main exposed-modules: Core, Database, Handlers, Logger, Main, Routes, Utility, Views

View File

@ -1,7 +1,5 @@
module Core where module Core where
import Control.Exception (IOException)
import Control.Monad.Catch (catch)
import Data.Aeson (FromJSON, ToJSON) import Data.Aeson (FromJSON, ToJSON)
import Data.Pool (Pool) import Data.Pool (Pool)
import qualified Data.Text as T import qualified Data.Text as T
@ -11,10 +9,10 @@ import Database.PostgreSQL.Simple.FromRow (FromRow, field, fromRow)
import Database.PostgreSQL.Simple.ToField (ToField, toField) import Database.PostgreSQL.Simple.ToField (ToField, toField)
import Database.PostgreSQL.Simple.ToRow (ToRow, toRow) import Database.PostgreSQL.Simple.ToRow (ToRow, toRow)
import Effectful import Effectful
import Effectful.Error.Static (Error, throwError) import Effectful.Error.Static (Error)
import Effectful.Reader.Static (Reader) import Effectful.Reader.Static (Reader)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Servant hiding ((:>), throwError) import Servant hiding ((:>))
import Servant.HTML.Lucid import Servant.HTML.Lucid
-- --
@ -67,19 +65,3 @@ data LogLevel = Info | Warning | Error
instance ToField LogLevel where instance ToField LogLevel where
toField level = toField (T.pack (show level)) toField level = toField (T.pack (show level))
--
-- Utility
--
liftIOE :: (IOE :> es, Error ServerError :> es) => IO a -> Eff es a
-- Lift IO into Eff and catch IOExceptions
liftIOE m = liftIO m `catch` \(e::IOException) -> do
-- Log IOExceptions to stdout
liftIO $ putStrLn $ "ERROR Exception: " ++ show e
-- Throw a custom Servant ServerError
throwError $ ServerError
{ errHTTPCode = 500
, errReasonPhrase = "Internal Server Error"
, errBody = "This incident will be investigated."
, errHeaders = []
}

View File

@ -1,6 +1,7 @@
module Database where module Database where
import Core import Core
import Utility
import Control.Exception (IOException) import Control.Exception (IOException)
import Data.Aeson (ToJSON) import Data.Aeson (ToJSON)
@ -70,28 +71,6 @@ runDatabaseIO = interpret $ \_ -> \case
=> (Pool Connection) -> (Connection -> IO a) -> Eff es a => (Pool Connection) -> (Connection -> IO a) -> Eff es a
liftWithPool p f = liftIOE $ withResource p f liftWithPool p f = liftIOE $ withResource p f
runDatabaseDebug :: DatabaseExeEffects es
=> Eff (Database : es) a -> Eff es a
runDatabaseDebug = interpret $ \_ -> \case
DatabaseInit -> do
liftIOE $ putStrLn "Mocked setup of the database"
DatabaseRead (statement, values) -> do
liftIOE $ putStrLn
$ "Mocked a READ database operation with statement:\n"
++ show statement
++ "\nValues:\n"
++ show values
pure []
DatabaseRead_ statement -> do
liftIOE $ putStrLn "Mocked a READ database operation on all users"
pure []
DatabaseWrite (statement, values) -> do
liftIOE $ putStrLn
$ "Mocked a WRITE database operation with statement:\n"
++ show statement
++ "\nValues:\n"
++ show values
createConnectionPool :: ByteString -> IO (Pool Connection) createConnectionPool :: ByteString -> IO (Pool Connection)
createConnectionPool connectString = newPool $ defaultPoolConfig createConnectionPool connectString = newPool $ defaultPoolConfig
(connectPostgreSQL connectString) (connectPostgreSQL connectString)

View File

@ -2,6 +2,7 @@ module Logger where
import Core import Core
import Database import Database
import Utility
import Data.Time (getCurrentTime, UTCTime) import Data.Time (getCurrentTime, UTCTime)
import Effectful import Effectful

View File

@ -47,14 +47,6 @@ runAppEff env = runEff
. runLoggerPSQL . runLoggerPSQL
. inject . inject
runAppDebug :: AppEnv -> AppEff a -> IO (Either ServerError a)
runAppDebug env = runEff
. runErrorNoCallStack
. runReader env
. runDatabaseDebug
. runLoggerConsole
. inject
port :: Int port :: Int
port = 8080 port = 8080

28
src/Utility.hs Normal file
View File

@ -0,0 +1,28 @@
module Utility where
import qualified Views as V
import Control.Exception (IOException)
import Control.Monad.Catch (catch)
import Effectful
import Effectful.Error.Static (Error, throwError)
import Lucid (renderBS)
import Servant ( ServerError(..)
, errHTTPCode
, errReasonPhrase
, errBody
, errHeaders
)
liftIOE :: (IOE :> es, Error ServerError :> es) => IO a -> Eff es a
-- Lift IO into Eff and catch IOExceptions
liftIOE m = liftIO m `catch` \(e::IOException) -> do
-- Log IOExceptions to stdout
liftIO $ putStrLn $ "ERROR Exception: " ++ show e
-- Throw a custom Servant ServerError
throwError $ ServerError
{ errHTTPCode = 500
, errReasonPhrase = "Internal Server Error"
, errBody = renderBS V.internalServerError
, errHeaders = []
}

View File

@ -32,3 +32,10 @@ userHtml user = div_ [] $ do
warning :: String -> Html () warning :: String -> Html ()
warning s = p_ [class_ "warning"] (toHtml s) warning s = p_ [class_ "warning"] (toHtml s)
internalServerError :: Html ()
internalServerError = baseDoc $ do
div_ [ style_ "text-align: center; margin: 3% 0 0 0;" ] $ do
h1_ "500 INTERNAL SERVER ERROR"
p_ "This issue is probably our fault. \
\ Please try again shortly or contact us for help."