/
Main.hs
97 lines (78 loc) · 2.92 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Applicative
import Control.Exception (SomeException)
import Control.Monad
import Control.Monad.CatchIO
import Control.Monad.Trans
import qualified Data.ByteString.Char8 as B
import Data.Lens.Template
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Time.Clock.POSIX
import Foreign.C.Types
import Prelude hiding (catch)
import Snap.Http.Server
import Snap.StaticPages
import Snap.Core
import Snap.Snaplet
import Snap.Snaplet.Heist
import Snap.Util.FileServe
import Snap.Util.GZip
import Text.Templating.Heist
import qualified Text.XHtmlCombinators.Escape as XH
data App = App
{ _heist :: Snaplet (Heist App)
, _blog :: Snaplet StaticPages
}
makeLenses [''App]
instance HasHeist App where heistLens = subSnaplet heist
epochTime :: IO CTime
epochTime = do
t <- getPOSIXTime
return $ fromInteger $ truncate t
description :: Text
description = "The snapframework.com website"
appInit :: SnapletInit App App
appInit = makeSnaplet "snap-website" description Nothing $ do
hs <- nestSnaplet "" heist $ heistInit "templates"
bs <- nestSnaplet "blog" blog $ staticPagesInit "blogdata"
addSplices [ ("snap-version", serverVersion)
, ("feed-autodiscovery-link", liftHeist $ textSplice "")
]
wrapHandlers (\h -> catch500 $ withCompression $
h <|> setCache (serveDirectory "static"))
return $ App hs bs
setCache :: MonadSnap m => m a -> m ()
setCache act = do
pinfo <- liftM rqPathInfo getRequest
act
when ("media" `B.isPrefixOf` pinfo) $ do
expTime <- liftM (+604800) $ liftIO epochTime
s <- liftIO $ formatHttpTime expTime
modifyResponse $
setHeader "Cache-Control" "public, max-age=604800" .
setHeader "Expires" s
catch500 :: MonadSnap m => m a -> m ()
catch500 m = (m >> return ()) `catch` \(e::SomeException) -> do
let t = T.pack $ show e
putResponse r
writeBS "<html><head><title>Internal Server Error</title></head>"
writeBS "<body><h1>Internal Server Error</h1>"
writeBS "<p>A web handler threw an exception. Details:</p>"
writeBS "<pre>\n"
writeText $ XH.escape t
writeBS "\n</pre></body></html>"
logError $ B.concat [ "caught exception: ", B.pack $ show e ]
where
r = setContentType "text/html" $
setResponseStatus 500 "Internal Server Error" emptyResponse
serverVersion :: SnapletSplice b v
serverVersion = liftHeist $ textSplice $ T.decodeUtf8 snapServerVersion
main :: IO ()
main = serveSnaplet defaultConfig appInit