webserver-0.6.0.0: Network/Web/Server/Params.hs
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS -Wall #-}
module Network.Web.Server.Params where
import Control.Applicative ((<$>))
import qualified Data.ByteString.Char8 as S
import qualified Data.ByteString.Lazy.Char8 as L
import Data.Time
import Data.Time.Clock.POSIX
import Network.TCPInfo
import Network.Web.HTTP
import System.Posix.Files
{-|
The configuration for the basic web server.
-}
data BasicConfig = BasicConfig {
-- | A mapper from 'URI' to 'Path'.
mapper :: Request -> Path
-- | Resource obtaining function. The second argument is
-- (offset of the resource, and length from the offset).
, obtain :: FilePath -> Maybe (Integer,Integer) -> IO L.ByteString
-- | A function to return the size of the resource and
-- its modification time if exists.
, info :: FilePath -> IO (Maybe (Integer, UTCTime))
-- | A server name specified the Server: field.
, serverName :: S.ByteString
-- | 'TCPInfo' for passing CGI. (See c10k library.)
, tcpInfo :: TCPInfo
}
{-|
Default 'BasicConfig', with 'obtain', 'info', and 'serverName' filled in.
It is necessary to override the 'mapper' and 'tcpInfo' fields
-}
defaultConfig :: BasicConfig
defaultConfig = BasicConfig
{ mapper = error "BasicConfig: no mapper defined"
, obtain = defaultObtain
, info = defaultInfo
, serverName = "BasicConfig: no server name"
, tcpInfo = error "BasicConfig: no TCPInfo"
}
{-|
Control information of how to handle 'URI'.
-}
data Path =
-- | 'URI' cannot be converted into any resources.
None
-- | 'URI' is converted into a resource (typically a file).
| File FilePath
-- | 'URI' is converted into CGI.
| PathCGI CGI
-- | 'URI' is converted into a handler callback
| Handler (IO Response)
instance Eq Path where
(File fp1) == (File fp2) = fp1 == fp2
(PathCGI cgi1) == (PathCGI cgi2) = cgi1 == cgi2
None == None = True
_ == _ = False
instance Show Path where
show None = "None"
show (File fp) = "File " ++ show fp
show (PathCGI cgi) = "PathCGI (" ++ show cgi ++ ")"
show (Handler _) = "Handler"
{-|
Internal information of CGI converted from 'URI'.
-}
data CGI = CGI {
-- | A program path to be executed.
progPath :: FilePath
-- | A script name.
, scriptName :: String
-- | A path information.
, pathInfo :: String
-- | A query string.
, queryString :: String
} deriving (Eq,Show)
-- | Get the size and modification time of a file, if possible.
defaultInfo :: FilePath -> IO (Maybe (Integer, UTCTime))
defaultInfo fp = do
exists <- fileExist fp
if exists
then do
status <- getFileStatus fp
let size = fromIntegral $ fileSize status
mt = posixSecondsToUTCTime . realToFrac $ modificationTime status
return $ Just (size,mt)
else return Nothing
-- | Obtain a data slice from a file as a lazy bytestring.
defaultObtain :: FilePath -> Maybe (Integer,Integer) -> IO L.ByteString
defaultObtain fp Nothing = L.readFile fp
defaultObtain fp (Just (offset,numBytes)) = L.take nb . L.drop ofs <$> L.readFile fp
where
nb = fromIntegral numBytes
ofs = fromIntegral offset