-
Notifications
You must be signed in to change notification settings - Fork 0
/
Main.hs
69 lines (51 loc) · 2.29 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
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
import Control.Monad (forM_)
import qualified Data.Attoparsec.Text as At
import Data.Default.Class (def)
import Data.Either (either)
import Data.String (fromString)
import qualified Data.Text as Text
import Data.Time (getZonedTime)
import qualified Network.HTTP.Types.Status as Status
import Network.Wai (Middleware)
import Network.Wai.Handler.Warp (setHost, setPort)
import qualified Network.Wai.Middleware.RequestLogger as Loggers
import System.Console.Docopt
import System.Environment (getArgs)
import System.Exit (exitFailure)
import Web.Scotty
main :: IO ()
main = do
args <- parseArgsOrExit patterns =<< getArgs
port <- args `getArgOrExit` (shortOption 'p')
host <- args `getArgOrExit` (shortOption 'H')
loggingMiddleware <- mkLoggingMiddleware
either
(const (exitWith "Invalid port. It has to be a numeric string."))
(runServer [loggingMiddleware] host)
(parsePort port)
runServer :: [Middleware] -> String -> Int -> IO ()
runServer middlewares host port = do
let opts = def { verbose = 1
, settings = setPort port $ setHost (fromString host) $ settings def }
scottyOpts opts (app middlewares)
app :: [Middleware] -> ScottyM ()
app middlewares = do
forM_ middlewares middleware
matchAny (regex "^/(.*)") $ status Status.noContent204
parsePort :: String -> Either String Int
parsePort = At.parseOnly At.decimal . Text.pack
mkLoggingMiddleware :: IO Middleware
mkLoggingMiddleware = return $ Loggers.logStdoutDev . printCurrentTimeMiddleware
printCurrentTimeMiddleware :: Middleware
printCurrentTimeMiddleware application req respond = do
time <- getZonedTime
putStrLn $ "\n" ++ show time
application req respond
getArgOrExit :: Arguments -> Option -> IO String
getArgOrExit = getArgOrExitWith patterns
exitWith :: String -> IO ()
exitWith reason = putStrLn reason >> exitFailure
patterns :: Docopt
patterns = [docoptFile|USAGE.txt|]