{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} module Hsm.Web ( Web , runServer , runWeb ) where import Effectful (Dispatch(Static), DispatchOf, Eff, IOE, (:>)) import Effectful.Dispatch.Static (SideEffects(WithSideEffects), StaticRep, evalStaticRep, getStaticRep, unEff, unsafeEff) import Effectful.Dispatch.Static.Primitive (Env) import Effectful.Exception (finally) import Hsm.Cam (Cam, capturePng) import Hsm.Log (Log, Severity(Info, Trace), logMsg, makeLoggerIO) import Network.Wai.Handler.Warp (defaultSettings, setLogger) import Paths_hsm_web (getDataFileName) import Web.Scotty (Options(settings, verbose), defaultOptions, file, get, liftIO, raw, scottyOpts, setHeader) data Web (a :: * -> *) (b :: *) type instance DispatchOf Web = Static WithSideEffects newtype instance StaticRep Web = Web Options server :: (Cam :> es, Log "cam" :> es) => Options -> Env es -> IO () server options env = do index <- getDataFileName "Html/index.html" scottyOpts options $ do get "/" $ file index get "/cam.png" $ do setHeader "Content-Type" "image/png" liftIO (unEff capturePng env) >>= raw runServer :: (Cam :> es, Log "cam" :> es, Log "web" :> es, Web :> es) => Eff es () runServer = finally startServer stopServer where startServer = do Web options <- getStaticRep logMsg @"web" Info "Starting scotty web server" unsafeEff $ server options stopServer = logMsg @"web" Info "Stopping scotty web server" runWeb :: (IOE :> es, Log "scotty" :> es, Log "web" :> es) => Eff (Web : es) a -> Eff es a runWeb action = do logMsg @"web" Info "Registering logger for scotty web server" scottyLogger <- makeLoggerIO @"scotty" >>= return . logRequest evalStaticRep (Web $ defaultOptions {verbose = 0, settings = setLogger scottyLogger defaultSettings}) action where logRequest loggerIO request status fileSize = loggerIO Trace $ unwords [show request, show status, show fileSize]