module Development.Duplo.Server where import Control.Monad.Trans (liftIO) import Data.List (intercalate) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as LT import Network.HTTP.Types (status200) import Network.Wai (pathInfo) import Network.Wai.Handler.Warp (Port) import System.Directory (doesFileExist) import System.Environment (getArgs) import System.FilePath.Posix (takeExtension) import Web.Scotty serve :: Port -> IO () serve port = do putStrLn $ "\n>> Starting server on port " ++ show port scotty port serve' serve' :: ScottyM () serve' = -- Always match because we're checking for files, not routes notFound $ do path <- fmap (intercalate "/" . fmap T.unpack . pathInfo) request -- Setting root let path' = "public/" ++ path exists <- liftIO $ doesFileExist path' status status200 if exists then normalFile path' else returnDefault path' normalFile :: FilePath -> ActionM () normalFile path = do let contentType = guessType path file path setHeader "Content-Type" $ LT.pack contentType -- | Return a default file depending on file type. Return the default HTML -- file otherwise. returnDefault :: FilePath -> ActionM () returnDefault path = do let extension = takeExtension path file $ case extension of ".css" -> "public/index.css" ".js" -> "public/index.js" _ -> "public/index.html" setHeader "Content-Type" $ case extension of ".css" -> "text/css" ".js" -> "text/javascript" _ -> "text/html" -- | "Guess" the content type from the path's file type guessType :: String -> String guessType path = case takeExtension path of ".htm" -> "text/html" ".html" -> "text/html" ".css" -> "text/css" ".js" -> "application/x-javascript" ".png" -> "image/png" ".jpeg" -> "image/jpeg" ".jpg" -> "image/jpeg" ".woff" -> "application/font-woff" ".ttf" -> "application/font-ttf" ".eot" -> "application/vnd.ms-fontobject" ".otf" -> "application/font-otf" ".svg" -> "image/svg+xml" otherwise -> "application/octet-stream"