-
-
Notifications
You must be signed in to change notification settings - Fork 139
/
Copy pathMain.hs
106 lines (92 loc) · 2.87 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
98
99
100
101
102
103
104
105
106
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeApplications #-}
module Main where
import Common
import Control.Concurrent
import Control.Monad
import Data.Binary.Builder
import Data.Monoid ((<>))
import Data.Proxy
import Data.Time.Clock
import qualified Lucid as L
import Lucid.Base
import Network.HTTP.Types
import Network.Wai
import Network.Wai.EventSource
import Network.Wai.Handler.Warp
import Network.Wai.Middleware.Gzip
import Network.Wai.Middleware.RequestLogger
import Servant
import qualified System.IO as IO
import Miso
port :: Int
port = 3003
main :: IO ()
main = do
IO.hPutStrLn IO.stderr ("Running on port " <> show port <> "...")
chan <- newChan
_ <- forkIO (sendEvents chan)
run port $ logStdout (compress (app chan))
where
compress = gzip def { gzipFiles = GzipCompress }
-- Send 1 event/s containing the current server time
sendEvents :: Chan ServerEvent -> IO ()
sendEvents chan =
forever $ do
time <- getCurrentTime
writeChan
chan
(ServerEvent Nothing Nothing [putStringUtf8 (show (show time))])
threadDelay (10 ^ (6 :: Int))
-- | Wrapper for setting HTML doctype and header
newtype Wrapper a = Wrapper a
deriving (Show, Eq)
instance L.ToHtml a => L.ToHtml (Wrapper a) where
toHtmlRaw = L.toHtml
toHtml (Wrapper x) =
L.doctypehtml_ $ do
L.head_ $ do
L.meta_ [L.charset_ "utf-8"]
jsRef "static/all.js" -- Include the frontend
L.body_ (L.toHtml x)
where
jsRef href =
L.with
(L.script_ mempty)
[ makeAttribute "src" href
, makeAttribute "async" mempty
, makeAttribute "defer" mempty
]
type ServerRoutes = ToServerRoutes ClientRoutes Wrapper Action
handle404 :: Application
handle404 _ respond =
respond $
responseLBS status404 [("Content-Type", "text/html")] $
renderBS $
toHtml $
Wrapper $ the404
type API = "static" :> Raw :<|> "sse" :> Raw :<|> ServerRoutes :<|> Raw
app :: Chan ServerEvent -> Application
app chan =
serve
(Proxy @API)
#if MIN_VERSION_servant(0,11,0)
(static :<|> Tagged (sseApp chan) :<|> (serverHandlers :<|> Tagged handle404))
#else
(static :<|> sseApp chan :<|> (serverHandlers :<|> handle404))
#endif
where
static = serveDirectory "static"
sseApp :: Chan ServerEvent -> Application
sseApp chan = eventSourceAppChan chan
serverHandlers :: Server ServerRoutes
serverHandlers = homeHandler
where
send f u =
pure $ Wrapper $ f Model {modelUri = u, modelMsg = "No event received"}
homeHandler = send home goHome