{-# LANGUAGE RecordWildCards #-} {-| This is the main module, which actually run the Breve webserver. -} module Main where -- Breve modules import Application (breve, emptyApp) import Breve.Settings import Breve.UrlTable import Paths_breve (getDataFileName) -- Data conversions import Data.Text (Text, unpack) import Data.String (IsString(..)) import Data.Maybe (listToMaybe) -- IO import Control.Monad (when, void) import Control.Exception as E import Control.Concurrent (forkIO) import System.Environment (getArgs) import Data.Text.IO as T -- Web server import Servant (Application) import Network.Wai.Handler.Warp (run, defaultSettings, setPort, setHost) import Network.Wai.Handler.WarpTLS (runTLS, TLSSettings) -- Middlewares import Network.Wai.Middleware.RequestLogger (logStdout) import Network.Wai.Middleware.ForceSSL (forceSSL) -- * Helpers -- | Runs Breve on the Warp webserver runApp :: AppSettings -> Application -> IO () runApp (AppSettings{..}) = runTLS tlsSettings warpSettings where host = unpack bindHost warpSettings = setPort bindPort $ setHost (fromString host) defaultSettings -- | Main -- -- Reads the configuration (given as the unique cli argument), -- sets things accordingly and runs the webserver. main :: IO () main = do configPath <- fmap listToMaybe getArgs config@(AppSettings{..}) <- settings configPath table <- load urlTable static <- getDataFileName "static/" -- Redirect from HTTP to HTTPS when listening -- on the standard port when (bindPort == 443) $ void $ forkIO (run 80 $ forceSSL emptyApp) -- Save the table just before exiting let exit E.UserInterrupt = save table urlTable exit e = throwIO e -- Middlewares are functions (Application -> Application). -- We use one here to add requests let middlewares = logStdout handle exit $ do T.putStrLn ("Serving on " <> bindUrl) runApp config (middlewares $ breve static bindUrl table)