{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Web.Spock.Config ( SpockCfg (..), defaultSpockCfg -- * Database , PoolOrConn (..), ConnBuilder (..), PoolCfg (..) -- * Sessions , defaultSessionCfg, SessionCfg (..) , defaultSessionHooks, SessionHooks (..) , SessionStore(..), SessionStoreInstance(..) , SV.newStmSessionStore ) where import Web.Spock.Action import Web.Spock.Internal.Types import qualified Web.Spock.Internal.SessionVault as SV #if MIN_VERSION_base(4,11,0) #elif MIN_VERSION_base(4,9,0) import Data.Semigroup #else import Data.Monoid #endif import Network.HTTP.Types.Status import System.IO import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.IO as T -- | NOP session hooks defaultSessionHooks :: SessionHooks a defaultSessionHooks = SessionHooks { sh_removed = const $ return () } -- | Session configuration with reasonable defaults and an -- stm based session store defaultSessionCfg :: a -> IO (SessionCfg conn a st) defaultSessionCfg emptySession = do store <- SV.newStmSessionStore return SessionCfg { sc_cookieName = "spockcookie" , sc_sessionTTL = 3600 , sc_sessionIdEntropy = 64 , sc_sessionExpandTTL = True , sc_emptySession = emptySession , sc_store = store , sc_housekeepingInterval = 60 * 10 , sc_hooks = defaultSessionHooks } -- | Spock configuration with reasonable defaults such as a basic error page -- and 5MB request body limit. IMPORTANT: CSRF Protection is turned off by -- default for now to not break any existing Spock applications. Consider -- turning it on manually as it will become the default in the future. defaultSpockCfg :: sess -> PoolOrConn conn -> st -> IO (SpockCfg conn sess st) defaultSpockCfg sess conn st = do defSess <- defaultSessionCfg sess return SpockCfg { spc_initialState = st , spc_database = conn , spc_sessionCfg = defSess , spc_maxRequestSize = Just (5 * 1024 * 1024) , spc_logError = T.hPutStrLn stderr , spc_errorHandler = errorHandler , spc_csrfProtection = False , spc_csrfHeaderName = "X-Csrf-Token" , spc_csrfPostName = "__csrf_token" } errorHandler :: Status -> ActionCtxT () IO () errorHandler status = html $ errorTemplate status -- Danger! This should better be done using combinators, but we do not -- want Spock depending on a specific html combinator framework errorTemplate :: Status -> T.Text errorTemplate s = "" <> "" <> message <> "" <> "" <> "" <> "

" <> message <> "

" <> "powered by Spock" <> "" where message = showT (statusCode s) <> " - " <> T.decodeUtf8 (statusMessage s) showT = T.pack . show