on master help sign in
CmdLine module
commit4fa99c130accb33f3499930b5dbf9d2f0675d63f authorMichael Snoyman <michael@snoyman.com> dateWed 26 Mar 2014, 14:52 (13 years ago) parentc0ab69c
3 files changed+113−94
wai-app-static/WaiAppStatic/CmdLine.hs+105 wai-app-static/app/warp-static.hs+3−90 wai-app-static/wai-app-static.cabal+5−4
wai-app-static/WaiAppStatic/CmdLine.hsnew file+105
@@ -0,0 +1,105 @@
1+{-# LANGUAGE DeriveDataTypeable, RecordWildCards #-}
2+-- | Command line version of wai-app-static, used for the warp-static server.
3+module WaiAppStatic.CmdLine
4+ ( runCommandLine
5+ , Args (..)
6+ ) where
7+
8+import Network.Wai (Middleware)
9+import Network.Wai.Application.Static (staticApp, defaultFileServerSettings)
10+import Network.Wai.Handler.Warp
11+ ( runSettings, defaultSettings, settingsHost, settingsPort
12+ )
13+import Options.Applicative
14+import Text.Printf (printf)
15+import System.Directory (canonicalizePath)
16+import Control.Monad (unless)
17+import Network.Wai.Middleware.Autohead
18+import Network.Wai.Middleware.RequestLogger (logStdout)
19+import Network.Wai.Middleware.Gzip
20+import qualified Data.Map as Map
21+import qualified Data.ByteString.Char8 as S8
22+import Control.Arrow ((***))
23+import Data.Text (pack)
24+import Data.String (fromString)
25+import Network.Mime (defaultMimeMap, mimeByExt, defaultMimeType)
26+import WaiAppStatic.Types (ssIndices, toPiece, ssGetMimeType, fileName, fromPiece)
27+import Data.Maybe (mapMaybe)
28+import Control.Arrow (second)
29+
30+data Args = Args
31+ { docroot :: FilePath
32+ , index :: [FilePath]
33+ , port :: Int
34+ , noindex :: Bool
35+ , quiet :: Bool
36+ , verbose :: Bool
37+ , mime :: [(String, String)]
38+ , host :: String
39+ }
40+
41+args :: Parser Args
42+args = Args
43+ <$> strOption
44+ ( long "docroot"
45+ <> short 'd'
46+ <> metavar "DOCROOT"
47+ <> value "."
48+ <> help "directory containing files to serve")
49+ <*> (defIndex <$> many (strOption
50+ ( long "index"
51+ <> short 'i'
52+ <> metavar "INDEX"
53+ <> help "index files to serve when a directory is required"
54+ )))
55+ <*> option
56+ ( long "port"
57+ <> short 'p'
58+ <> metavar "PORT"
59+ <> value 3000)
60+ <*> switch
61+ ( long "noindex"
62+ <> short 'n')
63+ <*> switch
64+ ( long "quiet"
65+ <> short 'q')
66+ <*> switch
67+ ( long "verbose"
68+ <> short 'v')
69+ <*> many (toPair <$> strOption
70+ ( long "mime"
71+ <> short 'm'
72+ <> metavar "MIME"
73+ <> help "extra file extension/mime type mappings"))
74+ <*> strOption
75+ ( long "host"
76+ <> short 'h'
77+ <> metavar "HOST"
78+ <> value "*"
79+ <> help "interface to bind to, special values: *, *4, *6")
80+ where
81+ toPair = second (drop 1) . break (== '=')
82+ defIndex [] = ["index.html", "index.htm"]
83+ defIndex x = x
84+
85+-- | Run with the given middleware and parsing options from the command line.
86+--
87+-- Since 2.0.1
88+runCommandLine :: (Args -> Middleware) -> IO ()
89+runCommandLine middleware = do
90+ args@Args {..} <- execParser $ info (helper <*> args) fullDesc
91+ let mime' = map (pack *** S8.pack) mime
92+ let mimeMap = Map.fromList mime' `Map.union` defaultMimeMap
93+ docroot' <- canonicalizePath docroot
94+ unless quiet $ printf "Serving directory %s on port %d with %s index files.\n" docroot' port (if noindex then "no" else show index)
95+ let middle = gzip def { gzipFiles = GzipCompress }
96+ . (if verbose then logStdout else id)
97+ . autohead
98+ . (middleware args)
99+ runSettings defaultSettings
100+ { settingsPort = port
101+ , settingsHost = fromString host
102+ } $ middle $ staticApp (defaultFileServerSettings $ fromString docroot)
103+ { ssIndices = if noindex then [] else mapMaybe (toPiece . pack) index
104+ , ssGetMimeType = return . mimeByExt mimeMap defaultMimeType . fromPiece . fileName
105+ }
wai-app-static/app/warp-static.hs+3−90
@@ -1,94 +1,7 @@
11{-# LANGUAGE DeriveDataTypeable, RecordWildCards #-}
2−import Network.Wai.Application.Static (staticApp, defaultFileServerSettings)
3−import Network.Wai.Handler.Warp
4− ( runSettings, defaultSettings, settingsHost, settingsPort
5− )
6−import Options.Applicative
7−import Text.Printf (printf)
8−import System.Directory (canonicalizePath)
9−import Control.Monad (unless)
10−import Network.Wai.Middleware.Autohead
11−import Network.Wai.Middleware.RequestLogger (logStdout)
12−import Network.Wai.Middleware.Gzip
13−import qualified Data.Map as Map
14−import qualified Data.ByteString.Char8 as S8
15−import Control.Arrow ((***))
16−import Data.Text (pack)
17−import Data.String (fromString)
18−import Network.Mime (defaultMimeMap, mimeByExt, defaultMimeType)
19−import WaiAppStatic.Types (ssIndices, toPiece, ssGetMimeType, fileName, fromPiece)
20−import Data.Maybe (mapMaybe)
21−import Control.Arrow (second)
2+module Main (main) where
223
23−data Args = Args
24− { docroot :: FilePath
25− , index :: [FilePath]
26− , port :: Int
27− , noindex :: Bool
28− , quiet :: Bool
29− , verbose :: Bool
30− , mime :: [(String, String)]
31− , host :: String
32− }
33−
34−args :: Parser Args
35−args = Args
36− <$> strOption
37− ( long "docroot"
38− <> short 'd'
39− <> metavar "DOCROOT"
40− <> value "."
41− <> help "directory containing files to serve")
42− <*> (defIndex <$> many (strOption
43− ( long "index"
44− <> short 'i'
45− <> metavar "INDEX"
46− <> help "index files to serve when a directory is required"
47− )))
48− <*> option
49− ( long "port"
50− <> short 'p'
51− <> metavar "PORT"
52− <> value 3000)
53− <*> switch
54− ( long "noindex"
55− <> short 'n')
56− <*> switch
57− ( long "quiet"
58− <> short 'q')
59− <*> switch
60− ( long "verbose"
61− <> short 'v')
62− <*> many (toPair <$> strOption
63− ( long "mime"
64− <> short 'm'
65− <> metavar "MIME"
66− <> help "extra file extension/mime type mappings"))
67− <*> strOption
68− ( long "host"
69− <> short 'h'
70− <> metavar "HOST"
71− <> value "*"
72− <> help "interface to bind to, special values: *, *4, *6")
73− where
74− toPair = second (drop 1) . break (== '=')
75− defIndex [] = ["index.html", "index.htm"]
76− defIndex x = x
4+import WaiAppStatic.CmdLine (runCommandLine)
775
786main :: IO ()
79−main = do
80− Args {..} <- execParser $ info (helper <*> args) fullDesc
81− let mime' = map (pack *** S8.pack) mime
82− let mimeMap = Map.fromList mime' `Map.union` defaultMimeMap
83− docroot' <- canonicalizePath docroot
84− unless quiet $ printf "Serving directory %s on port %d with %s index files.\n" docroot' port (if noindex then "no" else show index)
85− let middle = gzip def { gzipFiles = GzipCompress }
86− . (if verbose then logStdout else id)
87− . autohead
88− runSettings defaultSettings
89− { settingsPort = port
90− , settingsHost = fromString host
91− } $ middle $ staticApp (defaultFileServerSettings $ fromString docroot)
92− { ssIndices = if noindex then [] else mapMaybe (toPiece . pack) index
93− , ssGetMimeType = return . mimeByExt mimeMap defaultMimeType . fromPiece . fileName
94− }
7+main = runCommandLine (const id)
wai-app-static/wai-app-static.cabal+5−4
@@ -1,5 +1,5 @@
11name: wai-app-static
2−version: 2.0.0.6
2+version: 2.0.1
33license: MIT
44license-file: LICENSE
55author: Michael Snoyman <michael@snoyman.com>
@@ -50,12 +50,16 @@ library
5050 , template-haskell >= 2.7
5151 , zlib >= 0.5
5252 , filepath
53+ , wai-extra >= 2.0 && < 2.2
54+ , optparse-applicative >= 0.7
55+ , warp >= 2.0 && < 2.2
5356
5457 exposed-modules: Network.Wai.Application.Static
5558 WaiAppStatic.Storage.Filesystem
5659 WaiAppStatic.Storage.Embedded
5760 WaiAppStatic.Listing
5861 WaiAppStatic.Types
62+ WaiAppStatic.CmdLine
5963 other-modules: Util
6064 WaiAppStatic.Storage.Embedded.Runtime
6165 WaiAppStatic.Storage.Embedded.TH
@@ -69,15 +73,12 @@ Executable warp
6973 Main-is: warp-static.hs
7074 hs-source-dirs: app
7175 Build-depends: base >= 4 && < 5
72− , warp >= 2.0 && < 2.2
7376 , wai-app-static >= 2.0 && < 2.1
74− , wai-extra >= 2.0 && < 2.2
7577 , directory >= 1.0
7678 , containers >= 0.2
7779 , bytestring >= 0.9.1.4
7880 , text >= 0.7
7981 , mime-types >= 0.1 && < 0.2
80− , optparse-applicative >= 0.7
8182
8283test-suite runtests
8384 hs-source-dirs: test