-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Web related tools and services. -- -- Happstack Server provides an HTTP server and a rich set of functions -- for routing requests, handling query parameters, generating responses, -- working with cookies, serving files, and more. For in-depth -- documentation see the Happstack Crash Course -- http://happstack.com/docs/crashcourse/index.html @package happstack-server @version 7.1.1 module Happstack.Server.Internal.Socket -- | alternative implementation of accept to work around EAI_AGAIN errors acceptLite :: Socket -> IO (Socket, HostName, PortNumber) sockAddrToHostName :: SockAddr -> HostName module Happstack.Server.Internal.LogFormat -- | Format the time as describe in the Apache combined log format. -- http:httpd.apache.orgdocs2.2/logs.html#combined -- -- The format is: [daymonthyear:hour:minute:second zone] day = -- 2*digit month = 3*letter year = 4*digit hour = 2*digit minute = -- 2*digit second = 2*digit zone = (+ | -) 4*digit formatTimeCombined :: FormatTime t => t -> String -- | Format the request as describe in the Apache combined log format. -- http:httpd.apache.orgdocs2.2/logs.html#combined -- -- The format is: %h - %u %t "%r" %>s %b "%{Referer}i" -- "%{User-agent}i" %h: This is the IP address of the client (remote -- host) which made the request to the server. %u: This is the userid of -- the person requesting the document as determined by HTTP -- authentication. %t: The time that the request was received. %r: The -- request line from the client is given in double quotes. %>s: This -- is the status code that the server sends back to the client. %b: The -- last part indicates the size of the object returned to the client, not -- including the response headers. %{Referer}: The Referer (sic) -- HTTP request header. %{User-agent}: The User-Agent HTTP request -- header. formatRequestCombined :: FormatTime t => String -> String -> t -> String -> Int -> Integer -> String -> String -> String module Happstack.Server.Internal.TimeoutManager -- | A timeout manager data Manager data Handle initialize :: Int -> IO Manager register :: Manager -> IO () -> IO Handle registerKillThread :: Manager -> IO Handle tickle :: Handle -> IO () pause :: Handle -> IO () resume :: Handle -> IO () cancel :: Handle -> IO () module Happstack.Server.Internal.TimeoutIO -- | TimeoutIO is a record which abstracts out all the network IO functions -- needed by the request handling loop. This allows use to use the same -- event loop for handle both http: and https:. data TimeoutIO TimeoutIO :: Handle -> (ByteString -> IO ()) -> (ByteString -> IO ()) -> IO ByteString -> (FilePath -> Offset -> ByteCount -> IO ()) -> IO () -> Bool -> TimeoutIO toHandle :: TimeoutIO -> Handle toPutLazy :: TimeoutIO -> ByteString -> IO () toPut :: TimeoutIO -> ByteString -> IO () toGetContents :: TimeoutIO -> IO ByteString toSendFile :: TimeoutIO -> FilePath -> Offset -> ByteCount -> IO () toShutdown :: TimeoutIO -> IO () toSecure :: TimeoutIO -> Bool -- | module Happstack.Server.Internal.TimeoutSocket sPutLazyTickle :: Handle -> Socket -> ByteString -> IO () sPutTickle :: Handle -> Socket -> ByteString -> IO () sGetContents :: Handle -> Socket -> IO ByteString sendFileTickle :: Handle -> Socket -> FilePath -> Offset -> ByteCount -> IO () iterTickle :: Handle -> IO Iter -> IO () timeoutSocketIO :: Handle -> Socket -> TimeoutIO -- | A wrapper and type class so that functions like seeOther can -- take a URI which is represented by a String, URI, or -- other instance of ToSURI. module Happstack.Server.SURI -- | Retrieves the path component from the URI path :: SURI -> String -- | Retrieves the query component from the URI query :: SURI -> String -- | Retrieves the scheme component from the URI scheme :: SURI -> String -- | Modifies the scheme component of the URI using the provided function u_scheme :: (String -> String) -> SURI -> SURI -- | Modifies the path component of the URI using the provided function u_path :: (String -> String) -> SURI -> SURI -- | Sets the scheme component of the URI a_scheme :: String -> SURI -> SURI -- | Sets the path component of the URI a_path :: String -> SURI -> SURI escape :: String -> String unEscapeQS :: String -> String unEscape :: String -> String -- | Returns true if the URI is absolute isAbs :: SURI -> Bool newtype SURI SURI :: URI -> SURI suri :: SURI -> URI -- | Render should be used for prettyprinting URIs. render :: ToSURI a => a -> String -- | Parses a URI from a String. Returns Nothing on failure. parse :: String -> Maybe SURI -- | Convenience class for converting data types to URIs class ToSURI x toSURI :: ToSURI x => x -> SURI class FromPath x fromPath :: FromPath x => String -> x instance [overlap ok] Typeable SURI instance [overlap ok] Eq SURI instance [overlap ok] Data SURI instance [overlap ok] ToSURI Text instance [overlap ok] ToSURI Text instance [overlap ok] ToSURI String instance [overlap ok] ToSURI URI instance [overlap ok] ToSURI SURI instance [overlap ok] Ord SURI instance [overlap ok] Read SURI instance [overlap ok] Show SURI module Happstack.Server.Internal.Cookie -- | a type for HTTP cookies. Usually created using mkCookie. data Cookie Cookie :: String -> String -> String -> String -> String -> Bool -> Bool -> Cookie cookieVersion :: Cookie -> String cookiePath :: Cookie -> String cookieDomain :: Cookie -> String cookieName :: Cookie -> String cookieValue :: Cookie -> String secure :: Cookie -> Bool httpOnly :: Cookie -> Bool -- | Specify the lifetime of a cookie. -- -- Note that we always set the max-age and expires headers because -- internet explorer does not honor max-age. You can specific -- MaxAge or Expires and the other will be calculated for -- you. Choose which ever one makes your life easiest. data CookieLife -- | session cookie - expires when browser is closed Session :: CookieLife -- | life time of cookie in seconds MaxAge :: Int -> CookieLife -- | cookie expiration date Expires :: UTCTime -> CookieLife -- | cookie already expired Expired :: CookieLife calcLife :: CookieLife -> IO (Maybe (Int, UTCTime)) -- | Creates a cookie with a default version of 1, empty domain, a path of -- /, secure == False and httpOnly == False -- -- see also: addCookie mkCookie :: String -> String -> Cookie -- | Set a Cookie in the Result. The values are escaped as per RFC 2109, -- but some browsers may have buggy support for cookies containing e.g. -- '"' or ' '. -- -- Also, it seems that chrome, safari, and other webkit browsers do not -- like cookies which have double quotes around the domain and -- reject/ignore the cookie. So, we no longer quote the domain. -- -- internet explorer does not honor the max-age directive so we set both -- max-age and expires. -- -- See CookieLife and calcLife for a convenient way of -- calculating the first argument to this function. mkCookieHeader :: Maybe (Int, UTCTime) -> Cookie -> String -- | Get all cookies from the HTTP request. The cookies are ordered per RFC -- from the most specific to the least specific. Multiple cookies with -- the same name are allowed to exist. getCookies :: Monad m => ByteString -> m [Cookie] -- | Get the most specific cookie with the given name. Fails if there is no -- such cookie or if the browser did not escape cookies in a proper -- fashion. Browser support for escaping cookies properly is very -- diverse. getCookie :: Monad m => String -> ByteString -> m Cookie getCookies' :: Monad m => ByteString -> m (Either String [Cookie]) getCookie' :: Monad m => String -> ByteString -> m (Either String Cookie) -- | Not an supported api. Takes a cookie header and returns either a -- String error message or an array of parsed cookies parseCookies :: String -> Either String [Cookie] -- | not a supported api. A parser for RFC 2109 cookies cookiesParser :: GenParser Char st [Cookie] instance [overlap ok] Typeable Cookie instance [overlap ok] Typeable CookieLife instance [overlap ok] Show Cookie instance [overlap ok] Eq Cookie instance [overlap ok] Read Cookie instance [overlap ok] Data Cookie instance [overlap ok] Eq CookieLife instance [overlap ok] Ord CookieLife instance [overlap ok] Read CookieLife instance [overlap ok] Show CookieLife module Happstack.Server.Internal.Types -- | an HTTP request data Request Request :: Bool -> Method -> [String] -> String -> String -> [(String, Input)] -> MVar [(String, Input)] -> [(String, Cookie)] -> HttpVersion -> Headers -> MVar RqBody -> Host -> Request -- | request uses https:// rqSecure :: Request -> Bool -- | request method rqMethod :: Request -> Method -- | the uri, split on /, and then decoded rqPaths :: Request -> [String] -- | the raw rqUri rqUri :: Request -> String -- | the QUERY_STRING rqQuery :: Request -> String -- | the QUERY_STRING decoded as key/value pairs rqInputsQuery :: Request -> [(String, Input)] -- | the request body decoded as key/value pairs (when appropriate) rqInputsBody :: Request -> MVar [(String, Input)] -- | cookies rqCookies :: Request -> [(String, Cookie)] -- | HTTP version rqVersion :: Request -> HttpVersion -- | the HTTP request headers rqHeaders :: Request -> Headers -- | the raw, undecoded request body rqBody :: Request -> MVar RqBody -- | (hostname, port) of the client making the request rqPeer :: Request -> Host -- | an HTTP Response data Response Response :: Int -> Headers -> RsFlags -> ByteString -> Maybe (Response -> IO Response) -> Response rsCode :: Response -> Int rsHeaders :: Response -> Headers rsFlags :: Response -> RsFlags rsBody :: Response -> ByteString rsValidator :: Response -> Maybe (Response -> IO Response) SendFile :: Int -> Headers -> RsFlags -> Maybe (Response -> IO Response) -> FilePath -> Integer -> Integer -> Response rsCode :: Response -> Int rsHeaders :: Response -> Headers rsFlags :: Response -> RsFlags rsValidator :: Response -> Maybe (Response -> IO Response) -- | file handle to send from sfFilePath :: Response -> FilePath -- | offset to start at sfOffset :: Response -> Integer -- | number of bytes to send sfCount :: Response -> Integer -- | The body of an HTTP Request newtype RqBody Body :: ByteString -> RqBody unBody :: RqBody -> ByteString -- | a value extract from the QUERY_STRING or Request body -- -- If the input value was a file, then it will be saved to a temporary -- file on disk and inputValue will contain Left -- pathToTempFile. data Input Input :: Either FilePath ByteString -> Maybe FilePath -> ContentType -> Input inputValue :: Input -> Either FilePath ByteString inputFilename :: Input -> Maybe FilePath inputContentType :: Input -> ContentType -- | an HTTP header data HeaderPair HeaderPair :: ByteString -> [ByteString] -> HeaderPair -- | header name hName :: HeaderPair -> ByteString -- | header value (or values if multiple occurances of the header are -- present) hValue :: HeaderPair -> [ByteString] -- | get the request body from the Request and replace it with Nothing -- -- IMPORTANT: You can really only call this function once. Subsequent -- calls will return Nothing. takeRequestBody :: MonadIO m => Request -> m (Maybe RqBody) -- | read the request body inputs -- -- This will only work if the body inputs have already been decoded. -- Otherwise it will return Nothing. readInputsBody :: Request -> IO (Maybe [(String, Input)]) -- | Converts a Request into a String representing the corresponding URL rqURL :: Request -> String -- | Takes a list of (key,val) pairs and converts it into Headers. The keys -- will be converted to lowercase mkHeaders :: [(String, String)] -> Headers -- | Lookup header value. Key is case-insensitive. getHeader :: HasHeaders r => String -> r -> Maybe ByteString -- | Lookup header value. Key is a case-insensitive bytestring. getHeaderBS :: HasHeaders r => ByteString -> r -> Maybe ByteString -- | Lookup header value with a case-sensitive key. The key must be -- lowercase. getHeaderUnsafe :: HasHeaders r => ByteString -> r -> Maybe ByteString -- | Returns True if the associated key is found in the Headers. The lookup -- is case insensitive. hasHeader :: HasHeaders r => String -> r -> Bool -- | Acts as hasHeader with ByteStrings hasHeaderBS :: HasHeaders r => ByteString -> r -> Bool -- | Acts as hasHeaderBS but the key is case sensitive. It should be -- in lowercase. hasHeaderUnsafe :: HasHeaders r => ByteString -> r -> Bool -- | Associates the key/value pair in the headers. Forces the key to be -- lowercase. setHeader :: HasHeaders r => String -> String -> r -> r -- | Acts as setHeader but with ByteStrings. setHeaderBS :: HasHeaders r => ByteString -> ByteString -> r -> r -- | Sets the key to the HeaderPair. This is the only way to associate a -- key with multiple values via the setHeader* functions. Does not force -- the key to be in lowercase or guarantee that the given key and the key -- in the HeaderPair will match. setHeaderUnsafe :: HasHeaders r => ByteString -> HeaderPair -> r -> r -- | Add a key/value pair to the header. If the key already has a value -- associated with it, then the value will be appended. Forces the key to -- be lowercase. addHeader :: HasHeaders r => String -> String -> r -> r -- | Acts as addHeader except for ByteStrings addHeaderBS :: HasHeaders r => ByteString -> ByteString -> r -> r -- | Add a key/value pair to the header using the underlying HeaderPair -- data type. Does not force the key to be in lowercase or guarantee that -- the given key and the key in the HeaderPair will match. addHeaderUnsafe :: HasHeaders r => ByteString -> HeaderPair -> r -> r -- | Sets the Response status code to the provided Int and lifts the -- computation into a Monad. setRsCode :: Monad m => Int -> Response -> m Response -- | function to log access requests (see also: logMAccess) type -- LogAccess time = ( String -- ^ host -> String -- ^ user -> time -- -- ^ time -> String -- ^ requestLine -> Int -- ^ responseCode -- -> Integer -- ^ size -> String -- ^ referer -> String -- ^ -- userAgent -> IO ()) type LogAccess time = String -> String -> time -> String -> Int -> Integer -> String -> String -> IO () -- | log access requests using hslogger and apache-style log formatting -- -- see also: Conf logMAccess :: FormatTime t => LogAccess t -- | HTTP configuration data Conf Conf :: Int -> Maybe (Response -> IO Response) -> (forall t. FormatTime t => Maybe (LogAccess t)) -> Int -> Maybe ThreadGroup -> Conf -- | Port for the server to listen on. port :: Conf -> Int -- | a function to validate the output on-the-fly validator :: Conf -> Maybe (Response -> IO Response) -- | function to log access requests (see also: logMAccess) logAccess :: Conf -> forall t. FormatTime t => Maybe (LogAccess t) -- | number of seconds to wait before killing an inactive thread timeout :: Conf -> Int -- | ThreadGroup for registering spawned threads for handling requests threadGroup :: Conf -> Maybe ThreadGroup -- | Default configuration contains no validator and the port is set to -- 8000 nullConf :: Conf -- | Creates a Response with the given Int as the status code and the -- provided String as the body of the Response result :: Int -> String -> Response -- | Acts as result but works with ByteStrings directly. -- -- By default, Transfer-Encoding: chunked will be used resultBS :: Int -> ByteString -> Response -- | Sets the Response's status code to the given Int and redirects to the -- given URI redirect :: ToSURI s => Int -> s -> Response -> Response -- | True if Request is HTTP version 1.0 isHTTP1_0 :: Request -> Bool -- | True if Request is HTTP version 1.1 isHTTP1_1 :: Request -> Bool -- | Result flags data RsFlags RsFlags :: Length -> RsFlags rsfLength :: RsFlags -> Length -- | Default RsFlags: automatically use Transfer-Encoding: -- Chunked. nullRsFlags :: RsFlags -- | Automatically add a Content-Length header. Do not use -- Transfer-Encoding: Chunked contentLength :: Response -> Response -- | Do not automatically add a Content-Length header. Do automatically use -- Transfer-Encoding: Chunked chunked :: Response -> Response -- | Do not automatically add a Content-Length field to the Response noContentLength :: Response -> Response -- | HTTP version data HttpVersion HttpVersion :: Int -> Int -> HttpVersion -- | A flag value set in the Response which controls how the -- Content-Length header is set, and whether *chunked* output -- encoding is used. -- -- see also: nullRsFlags, notContentLength, and -- chunked data Length -- | automatically add a Content-Length header to the -- Response ContentLength :: Length -- | do not add a Content-Length header. Do use chunked -- output encoding TransferEncodingChunked :: Length -- | do not set Content-Length or chunked output -- encoding. NoContentLength :: Length -- | HTTP request method data Method GET :: Method HEAD :: Method POST :: Method PUT :: Method DELETE :: Method TRACE :: Method OPTIONS :: Method CONNECT :: Method -- | a Map of HTTP headers -- -- the Map key is the header converted to lowercase type Headers = Map ByteString HeaderPair -- | Should the connection be used for further messages after this. -- isHTTP1_0 && hasKeepAlive || isHTTP1_1 && -- hasNotConnectionClose -- -- In addition to this rule All 1xx (informational), 204 (no content), -- and 304 (not modified) responses MUST NOT include a message-body and -- therefore are eligible for connection keep-alive. continueHTTP :: Request -> Response -> Bool -- | hostname & port type Host = (String, Int) -- | A MIME media type value. The Show instance is derived -- automatically. Use showContentType to obtain the standard -- string representation. See http://www.ietf.org/rfc/rfc2046.txt -- for more information about MIME media types. data ContentType ContentType :: String -> String -> [(String, String)] -> ContentType -- | The top-level media type, the general type of the data. Common -- examples are "text", "image", "audio", "video", "multipart", and -- "application". ctType :: ContentType -> String -- | The media subtype, the specific data format. Examples include "plain", -- "html", "jpeg", "form-data", etc. ctSubtype :: ContentType -> String -- | Media type parameters. On common example is the charset parameter for -- the "text" top-level type, e.g. ("charset","ISO-8859-1"). ctParameters :: ContentType -> [(String, String)] readDec' :: (Num a, Eq a) => String -> a -- | convert a 'ReadS a' result to 'Maybe a' fromReadS :: [(a, String)] -> Maybe a -- | Read in any monad. readM :: (Monad m, Read t) => String -> m t -- | This class is used by path to parse a path component into a -- value. -- -- The instances for number types (Int, Float, etc) use -- readM to parse the path component. -- -- The instance for String, on the other hand, returns the -- unmodified path component. -- -- See the following section of the Happstack Crash Course for detailed -- instructions using and extending FromReqURI: -- -- -- http://www.happstack.com/docs/crashcourse/RouteFilters.html#FromReqURI class FromReqURI a fromReqURI :: FromReqURI a => String -> Maybe a instance [overlap ok] Typeable Method instance [overlap ok] Typeable RsFlags instance [overlap ok] Typeable Input instance [overlap ok] Typeable Response instance [overlap ok] Typeable RqBody instance [overlap ok] Typeable Request instance [overlap ok] Read HttpVersion instance [overlap ok] Eq HttpVersion instance [overlap ok] Show Method instance [overlap ok] Read Method instance [overlap ok] Eq Method instance [overlap ok] Ord Method instance [overlap ok] Data Method instance [overlap ok] Read HeaderPair instance [overlap ok] Show HeaderPair instance [overlap ok] Eq Length instance [overlap ok] Ord Length instance [overlap ok] Read Length instance [overlap ok] Show Length instance [overlap ok] Enum Length instance [overlap ok] Show RsFlags instance [overlap ok] Read RsFlags instance [overlap ok] Show Input instance [overlap ok] Read Input instance [overlap ok] Read RqBody instance [overlap ok] Show RqBody instance [overlap ok] FromReqURI Bool instance [overlap ok] FromReqURI Double instance [overlap ok] FromReqURI Float instance [overlap ok] FromReqURI Word64 instance [overlap ok] FromReqURI Word32 instance [overlap ok] FromReqURI Word16 instance [overlap ok] FromReqURI Word8 instance [overlap ok] FromReqURI Word instance [overlap ok] FromReqURI Integer instance [overlap ok] FromReqURI Int64 instance [overlap ok] FromReqURI Int32 instance [overlap ok] FromReqURI Int16 instance [overlap ok] FromReqURI Int8 instance [overlap ok] FromReqURI Int instance [overlap ok] FromReqURI Char instance [overlap ok] FromReqURI Text instance [overlap ok] FromReqURI Text instance [overlap ok] FromReqURI String instance [overlap ok] HasHeaders Headers instance [overlap ok] HasHeaders Request instance [overlap ok] HasHeaders Response instance [overlap ok] Show Request instance [overlap ok] Error Response instance [overlap ok] Show Response instance [overlap ok] Show HttpVersion module Happstack.Server.Internal.Multipart -- | similar to the normal span function, except the predicate gets -- the whole rest of the lazy bytestring, not just one character. -- -- TODO: this function has not been profiled. spanS :: (ByteString -> Bool) -> ByteString -> (ByteString, ByteString) takeWhileS :: (ByteString -> Bool) -> ByteString -> ByteString crlf :: ByteString crlfcrlf :: ByteString blankLine :: ByteString dropWhileS :: (ByteString -> Bool) -> ByteString -> ByteString data BodyPart -- | headers body BodyPart :: ByteString -> ByteString -> BodyPart data Work BodyWork :: ContentType -> [(String, String)] -> ByteString -> Work HeaderWork :: ByteString -> Work type InputWorker = Work -> IO InputIter data InputIter Failed :: (Maybe (String, Input)) -> String -> InputIter BodyResult :: (String, Input) -> InputWorker -> InputIter HeaderResult :: [Header] -> InputWorker -> InputIter type FileSaver = FilePath -> Int64 -> FilePath -> ByteString -> IO (Bool, Int64, FilePath) defaultFileSaver :: FilePath -> Int64 -> FilePath -> ByteString -> IO (Bool, Int64, FilePath) defaultInputIter :: FileSaver -> FilePath -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Work -> IO InputIter hPutLimit :: Int64 -> Handle -> ByteString -> IO (Bool, Int64) hPutLimit' :: Int64 -> Handle -> Int64 -> ByteString -> IO (Bool, Int64) bodyPartToInput :: InputWorker -> BodyPart -> IO InputIter bodyPartsToInputs :: InputWorker -> [BodyPart] -> IO ([(String, Input)], Maybe String) multipartBody :: InputWorker -> ByteString -> ByteString -> IO ([(String, Input)], Maybe String) -- | Packs a string into an Input of type text/plain simpleInput :: String -> Input -- | The default content-type for variables. defaultInputType :: ContentType parseMultipartBody :: ByteString -> ByteString -> ([BodyPart], Maybe String) dropPreamble :: ByteString -> ByteString -> (ByteString, Maybe String) dropLine :: ByteString -> ByteString -- | Check whether a string starts with two dashes followed by the given -- boundary string. isBoundary :: ByteString -> ByteString -> Bool -- | Checks whether a string starts with two dashes. startsWithDashes :: ByteString -> Bool splitParts :: ByteString -> ByteString -> ([BodyPart], Maybe String) splitPart :: ByteString -> ByteString -> (BodyPart, ByteString) splitBlank :: ByteString -> (ByteString, ByteString) splitBoundary :: ByteString -> ByteString -> (ByteString, ByteString) splitAtEmptyLine :: ByteString -> Maybe (ByteString, ByteString) -- | Split a string at the first CRLF. The CRLF is not included in any of -- the returned strings. splitAtCRLF :: ByteString -> Maybe (ByteString, ByteString) instance [overlap ok] Eq BodyPart instance [overlap ok] Ord BodyPart instance [overlap ok] Read BodyPart instance [overlap ok] Show BodyPart module Happstack.Server.Internal.MessageWrap queryInput :: SURI -> [(String, Input)] -- | see defaultBodyPolicy data BodyPolicy BodyPolicy :: (Int64 -> Int64 -> Int64 -> InputWorker) -> Int64 -> Int64 -> Int64 -> BodyPolicy inputWorker :: BodyPolicy -> Int64 -> Int64 -> Int64 -> InputWorker -- | maximum bytes for files uploaded in this Request maxDisk :: BodyPolicy -> Int64 -- | maximum bytes for all non-file values in the Request body maxRAM :: BodyPolicy -> Int64 -- | maximum bytes of overhead for headers in multipart/form-data maxHeader :: BodyPolicy -> Int64 -- | create a BodyPolicy for use with decodeBody defaultBodyPolicy :: FilePath -> Int64 -> Int64 -> Int64 -> BodyPolicy bodyInput :: MonadIO m => BodyPolicy -> Request -> m ([(String, Input)], Maybe String) -- | Decodes application/x-www-form-urlencoded inputs. TODO: should any of -- the [] be error conditions? formDecode :: String -> [(String, Input)] decodeBody :: BodyPolicy -> Maybe ContentType -> ByteString -> IO ([(String, Input)], Maybe String) -- | Decodes multipart/form-data input. multipartDecode :: InputWorker -> [(String, String)] -> ByteString -> IO ([(String, Input)], Maybe String) -- | Get the path components from a String. pathEls :: String -> [String] -- | Repeadly splits a list by the provided separator and collects the -- results splitList :: Eq a => a -> [a] -> [[a]] -- | Repeatedly splits a list and collects the results splitListBy :: (a -> Bool) -> [a] -> [[a]] -- | Split is like break, but the matching element is dropped. split :: (a -> Bool) -> [a] -> ([a], [a]) defaultInputIter :: FileSaver -> FilePath -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Work -> IO InputIter module Happstack.Server.Internal.Handler request :: TimeoutIO -> Maybe (LogAccess UTCTime) -> Host -> (Request -> IO Response) -> IO () -- | Unserializes the bytestring into a response. If there is an error it -- will return Left msg. parseResponse :: ByteString -> Either String Response -- | Serializes the request to the given handle putRequest :: Handle -> Request -> IO () module Happstack.Server.Internal.Listen -- | Bind and listen port listen :: Conf -> (Request -> IO Response) -> IO () -- | Use a previously bind port and listen listen' :: Socket -> Conf -> (Request -> IO Response) -> IO () listenOn :: Int -> IO Socket listenOnIPv4 :: String -> Int -> IO Socket module Happstack.Server.Internal.LowLevel -- | a very simple interface for acting as an HTTP client. This is mostly -- used for things like Happstack.Server.Proxy. You are more -- likely to want a library like http-enumerator -- http://hackage.haskell.org/package/http-enumerator. module Happstack.Server.Client -- | Sends the serialized request to the host defined in the request and -- attempts to parse response upon arrival. getResponse :: Request -> IO (Either String Response) module Happstack.Server.Types -- | an HTTP request data Request Request :: Bool -> Method -> [String] -> String -> String -> [(String, Input)] -> MVar [(String, Input)] -> [(String, Cookie)] -> HttpVersion -> Headers -> MVar RqBody -> Host -> Request -- | request uses https:// rqSecure :: Request -> Bool -- | request method rqMethod :: Request -> Method -- | the uri, split on /, and then decoded rqPaths :: Request -> [String] -- | the raw rqUri rqUri :: Request -> String -- | the QUERY_STRING rqQuery :: Request -> String -- | the QUERY_STRING decoded as key/value pairs rqInputsQuery :: Request -> [(String, Input)] -- | the request body decoded as key/value pairs (when appropriate) rqInputsBody :: Request -> MVar [(String, Input)] -- | cookies rqCookies :: Request -> [(String, Cookie)] -- | HTTP version rqVersion :: Request -> HttpVersion -- | the HTTP request headers rqHeaders :: Request -> Headers -- | the raw, undecoded request body rqBody :: Request -> MVar RqBody -- | (hostname, port) of the client making the request rqPeer :: Request -> Host -- | an HTTP Response data Response Response :: Int -> Headers -> RsFlags -> ByteString -> Maybe (Response -> IO Response) -> Response rsCode :: Response -> Int rsHeaders :: Response -> Headers rsFlags :: Response -> RsFlags rsBody :: Response -> ByteString rsValidator :: Response -> Maybe (Response -> IO Response) SendFile :: Int -> Headers -> RsFlags -> Maybe (Response -> IO Response) -> FilePath -> Integer -> Integer -> Response rsCode :: Response -> Int rsHeaders :: Response -> Headers rsFlags :: Response -> RsFlags rsValidator :: Response -> Maybe (Response -> IO Response) -- | file handle to send from sfFilePath :: Response -> FilePath -- | offset to start at sfOffset :: Response -> Integer -- | number of bytes to send sfCount :: Response -> Integer -- | The body of an HTTP Request newtype RqBody Body :: ByteString -> RqBody unBody :: RqBody -> ByteString -- | a value extract from the QUERY_STRING or Request body -- -- If the input value was a file, then it will be saved to a temporary -- file on disk and inputValue will contain Left -- pathToTempFile. data Input Input :: Either FilePath ByteString -> Maybe FilePath -> ContentType -> Input inputValue :: Input -> Either FilePath ByteString inputFilename :: Input -> Maybe FilePath inputContentType :: Input -> ContentType -- | an HTTP header data HeaderPair HeaderPair :: ByteString -> [ByteString] -> HeaderPair -- | header name hName :: HeaderPair -> ByteString -- | header value (or values if multiple occurances of the header are -- present) hValue :: HeaderPair -> [ByteString] -- | get the request body from the Request and replace it with Nothing -- -- IMPORTANT: You can really only call this function once. Subsequent -- calls will return Nothing. takeRequestBody :: MonadIO m => Request -> m (Maybe RqBody) -- | read the request body inputs -- -- This will only work if the body inputs have already been decoded. -- Otherwise it will return Nothing. readInputsBody :: Request -> IO (Maybe [(String, Input)]) -- | Converts a Request into a String representing the corresponding URL rqURL :: Request -> String -- | Takes a list of (key,val) pairs and converts it into Headers. The keys -- will be converted to lowercase mkHeaders :: [(String, String)] -> Headers -- | Lookup header value. Key is case-insensitive. getHeader :: HasHeaders r => String -> r -> Maybe ByteString -- | Lookup header value. Key is a case-insensitive bytestring. getHeaderBS :: HasHeaders r => ByteString -> r -> Maybe ByteString -- | Lookup header value with a case-sensitive key. The key must be -- lowercase. getHeaderUnsafe :: HasHeaders r => ByteString -> r -> Maybe ByteString -- | Returns True if the associated key is found in the Headers. The lookup -- is case insensitive. hasHeader :: HasHeaders r => String -> r -> Bool -- | Acts as hasHeader with ByteStrings hasHeaderBS :: HasHeaders r => ByteString -> r -> Bool -- | Acts as hasHeaderBS but the key is case sensitive. It should be -- in lowercase. hasHeaderUnsafe :: HasHeaders r => ByteString -> r -> Bool -- | Associates the key/value pair in the headers. Forces the key to be -- lowercase. setHeader :: HasHeaders r => String -> String -> r -> r -- | Acts as setHeader but with ByteStrings. setHeaderBS :: HasHeaders r => ByteString -> ByteString -> r -> r -- | Sets the key to the HeaderPair. This is the only way to associate a -- key with multiple values via the setHeader* functions. Does not force -- the key to be in lowercase or guarantee that the given key and the key -- in the HeaderPair will match. setHeaderUnsafe :: HasHeaders r => ByteString -> HeaderPair -> r -> r -- | Add a key/value pair to the header. If the key already has a value -- associated with it, then the value will be appended. Forces the key to -- be lowercase. addHeader :: HasHeaders r => String -> String -> r -> r -- | Acts as addHeader except for ByteStrings addHeaderBS :: HasHeaders r => ByteString -> ByteString -> r -> r -- | Add a key/value pair to the header using the underlying HeaderPair -- data type. Does not force the key to be in lowercase or guarantee that -- the given key and the key in the HeaderPair will match. addHeaderUnsafe :: HasHeaders r => ByteString -> HeaderPair -> r -> r -- | Sets the Response status code to the provided Int and lifts the -- computation into a Monad. setRsCode :: Monad m => Int -> Response -> m Response -- | function to log access requests (see also: logMAccess) type -- LogAccess time = ( String -- ^ host -> String -- ^ user -> time -- -- ^ time -> String -- ^ requestLine -> Int -- ^ responseCode -- -> Integer -- ^ size -> String -- ^ referer -> String -- ^ -- userAgent -> IO ()) type LogAccess time = String -> String -> time -> String -> Int -> Integer -> String -> String -> IO () -- | log access requests using hslogger and apache-style log formatting -- -- see also: Conf logMAccess :: FormatTime t => LogAccess t -- | HTTP configuration data Conf Conf :: Int -> Maybe (Response -> IO Response) -> (forall t. FormatTime t => Maybe (LogAccess t)) -> Int -> Maybe ThreadGroup -> Conf -- | Port for the server to listen on. port :: Conf -> Int -- | a function to validate the output on-the-fly validator :: Conf -> Maybe (Response -> IO Response) -- | function to log access requests (see also: logMAccess) logAccess :: Conf -> forall t. FormatTime t => Maybe (LogAccess t) -- | number of seconds to wait before killing an inactive thread timeout :: Conf -> Int -- | ThreadGroup for registering spawned threads for handling requests threadGroup :: Conf -> Maybe ThreadGroup -- | Default configuration contains no validator and the port is set to -- 8000 nullConf :: Conf -- | Creates a Response with the given Int as the status code and the -- provided String as the body of the Response result :: Int -> String -> Response -- | Acts as result but works with ByteStrings directly. -- -- By default, Transfer-Encoding: chunked will be used resultBS :: Int -> ByteString -> Response -- | Sets the Response's status code to the given Int and redirects to the -- given URI redirect :: ToSURI s => Int -> s -> Response -> Response -- | True if Request is HTTP version 1.0 isHTTP1_0 :: Request -> Bool -- | True if Request is HTTP version 1.1 isHTTP1_1 :: Request -> Bool -- | Result flags data RsFlags RsFlags :: Length -> RsFlags rsfLength :: RsFlags -> Length -- | Default RsFlags: automatically use Transfer-Encoding: -- Chunked. nullRsFlags :: RsFlags -- | Automatically add a Content-Length header. Do not use -- Transfer-Encoding: Chunked contentLength :: Response -> Response -- | Do not automatically add a Content-Length header. Do automatically use -- Transfer-Encoding: Chunked chunked :: Response -> Response -- | Do not automatically add a Content-Length field to the Response noContentLength :: Response -> Response -- | HTTP version data HttpVersion HttpVersion :: Int -> Int -> HttpVersion -- | A flag value set in the Response which controls how the -- Content-Length header is set, and whether *chunked* output -- encoding is used. -- -- see also: nullRsFlags, notContentLength, and -- chunked data Length -- | automatically add a Content-Length header to the -- Response ContentLength :: Length -- | do not add a Content-Length header. Do use chunked -- output encoding TransferEncodingChunked :: Length -- | do not set Content-Length or chunked output -- encoding. NoContentLength :: Length -- | HTTP request method data Method GET :: Method HEAD :: Method POST :: Method PUT :: Method DELETE :: Method TRACE :: Method OPTIONS :: Method CONNECT :: Method -- | a Map of HTTP headers -- -- the Map key is the header converted to lowercase type Headers = Map ByteString HeaderPair -- | Should the connection be used for further messages after this. -- isHTTP1_0 && hasKeepAlive || isHTTP1_1 && -- hasNotConnectionClose -- -- In addition to this rule All 1xx (informational), 204 (no content), -- and 304 (not modified) responses MUST NOT include a message-body and -- therefore are eligible for connection keep-alive. continueHTTP :: Request -> Response -> Bool -- | hostname & port type Host = (String, Int) -- | A MIME media type value. The Show instance is derived -- automatically. Use showContentType to obtain the standard -- string representation. See http://www.ietf.org/rfc/rfc2046.txt -- for more information about MIME media types. data ContentType ContentType :: String -> String -> [(String, String)] -> ContentType -- | The top-level media type, the general type of the data. Common -- examples are "text", "image", "audio", "video", "multipart", and -- "application". ctType :: ContentType -> String -- | The media subtype, the specific data format. Examples include "plain", -- "html", "jpeg", "form-data", etc. ctSubtype :: ContentType -> String -- | Media type parameters. On common example is the charset parameter for -- the "text" top-level type, e.g. ("charset","ISO-8859-1"). ctParameters :: ContentType -> [(String, String)] readDec' :: (Num a, Eq a) => String -> a -- | convert a 'ReadS a' result to 'Maybe a' fromReadS :: [(a, String)] -> Maybe a -- | This class is used by path to parse a path component into a -- value. -- -- The instances for number types (Int, Float, etc) use -- readM to parse the path component. -- -- The instance for String, on the other hand, returns the -- unmodified path component. -- -- See the following section of the Happstack Crash Course for detailed -- instructions using and extending FromReqURI: -- -- -- http://www.happstack.com/docs/crashcourse/RouteFilters.html#FromReqURI class FromReqURI a fromReqURI :: FromReqURI a => String -> Maybe a -- | This module defines the Monad stack used by Happstack. You mostly -- don't want to be looking in here. Look in -- Happstack.Server.Monads instead. module Happstack.Server.Internal.Monads -- | An alias for WebT when using IO. type Web a = WebT IO a -- | An alias for ServerPartT IO type ServerPart a = ServerPartT IO a -- | ServerPartT is a rich, featureful monad for web development. -- -- see also: simpleHTTP, ServerMonad, FilterMonad, -- WebMonad, and HasRqData newtype ServerPartT m a ServerPartT :: ReaderT Request (WebT m) a -> ServerPartT m a unServerPartT :: ServerPartT m a -> ReaderT Request (WebT m) a -- | Particularly useful when combined with runWebT to produce a -- m (Maybe Response) from a Request. runServerPartT :: ServerPartT m a -> Request -> WebT m a -- | function for lifting WebT to ServerPartT -- -- NOTE: This is mostly for internal use. If you want to access the -- Request in user-code see askRq from ServerMonad. -- --
--   do request <- askRq
--      ...
--   
withRequest :: (Request -> WebT m a) -> ServerPartT m a -- | A constructor for a ServerPartT when you don't care about the -- request. -- -- NOTE: This is mostly for internal use. If you think you need to use it -- in your own code, you might consider asking on the mailing list or IRC -- to find out if there is an alternative solution. anyRequest :: Monad m => WebT m a -> ServerPartT m a -- | Apply a function to transform the inner monad of -- ServerPartT m. -- -- Often used when transforming a monad with ServerPartT, since -- simpleHTTP requires a ServerPartT IO -- a. Refer to UnWebT for an explanation of the structure of -- the monad. -- -- Here is an example. Suppose you want to embed an ErrorT into -- your ServerPartT to enable throwError and -- catchError in your Monad. -- --
--   type MyServerPartT e m a = ServerPartT (ErrorT e m) a
--   
-- -- Now suppose you want to pass MyServerPartT into a function -- that demands a ServerPartT IO a (e.g. -- simpleHTTP). You can provide the function: -- --
--   unpackErrorT :: (Monad m, Show e) => UnWebT (ErrorT e m) a -> UnWebT m a
--   unpackErrorT et = do
--      eitherV <- runErrorT et
--      return $ case eitherV of
--          Left err -> Just (Left $ toResponse $
--                                   "Catastrophic failure " ++ show err
--                           , filterFun $ \r -> r{rsCode = 500})
--          Right x -> x
--   
-- -- With unpackErrorT you can now call simpleHTTP. Just -- wrap your ServerPartT list. -- --
--   simpleHTTP nullConf $ mapServerPartT unpackErrorT (myPart `catchError` myHandler)
--   
-- -- Or alternatively: -- --
--   simpleHTTP' unpackErrorT nullConf (myPart `catchError` myHandler)
--   
-- -- Also see spUnwrapErrorT for a more sophisticated version of -- this function. mapServerPartT :: (UnWebT m a -> UnWebT n b) -> (ServerPartT m a -> ServerPartT n b) -- | A variant of mapServerPartT where the first argument also takes -- a Request. Useful if you want to runServerPartT on a -- different ServerPartT inside your monad (see -- spUnwrapErrorT). mapServerPartT' :: (Request -> UnWebT m a -> UnWebT n b) -> (ServerPartT m a -> ServerPartT n b) -- | The ServerMonad class provides methods for reading or locally -- modifying the Request. It is essentially a specialized version -- of the MonadReader class. Providing the unique names, -- askRq and localRq makes it easier to use -- ServerPartT and ReaderT together. class Monad m => ServerMonad m askRq :: ServerMonad m => m Request localRq :: ServerMonad m => (Request -> Request) -> m a -> m a -- | A monoid operation container. If a is a monoid, then -- SetAppend is a monoid with the following behaviors: -- --
--   Set    x `mappend` Append y = Set    (x `mappend` y)
--   Append x `mappend` Append y = Append (x `mappend` y)
--   _        `mappend` Set y    = Set y
--   
-- -- A simple way of summarizing this is, if the right side is -- Append, then the right is appended to the left. If the right -- side is Set, then the left side is ignored. data SetAppend a Set :: a -> SetAppend a Append :: a -> SetAppend a -- | Extract the value from a SetAppend. Note that a -- SetAppend is actually a CoPointed from: -- http://hackage.haskell.org/packages/archive/category-extras/latest/doc/html/Control-Functor-Pointed.html -- But lets not drag in that dependency. yet... extract :: SetAppend t -> t -- | FilterFun is a lot more fun to type than SetAppend -- (Dual (Endo a)). type FilterFun a = SetAppend (Dual (Endo a)) unFilterFun :: FilterFun a -> (a -> a) -- | turn a function into a FilterFun. Primarily used with -- mapServerPartT filterFun :: (a -> a) -> FilterFun a newtype FilterT a m b FilterT :: WriterT (FilterFun a) m b -> FilterT a m b unFilterT :: FilterT a m b -> WriterT (FilterFun a) m b -- | A set of functions for manipulating filters. -- -- ServerPartT implements FilterMonad Response so -- these methods are the fundamental ways of manipulating Response -- values. class Monad m => FilterMonad a m | m -> a setFilter :: FilterMonad a m => (a -> a) -> m () composeFilter :: FilterMonad a m => (a -> a) -> m () getFilter :: FilterMonad a m => m b -> m (b, a -> a) -- | Resets all your filters. An alias for setFilter -- id. ignoreFilters :: FilterMonad a m => m () -- | The basic Response building object. newtype WebT m a WebT :: ErrorT Response (FilterT (Response) (MaybeT m)) a -> WebT m a unWebT :: WebT m a -> ErrorT Response (FilterT (Response) (MaybeT m)) a -- | UnWebT is almost exclusively used with mapServerPartT. -- If you are not using mapServerPartT then you do not need to -- wrap your head around this type. If you are -- the type is not as -- complex as it first appears. -- -- It is worth discussing the unpacked structure of WebT a bit as -- it's exposed in mapServerPartT and mapWebT. -- -- A fully unpacked WebT has a structure that looks like: -- --
--   ununWebT $ WebT m a :: m (Maybe (Either Response a, FilterFun Response))
--   
-- -- So, ignoring m, as it is just the containing Monad, -- the outermost layer is a Maybe. This is Nothing if -- mzero was called or Just (Either -- Response a, SetAppend (Endo -- Response)) if mzero wasn't called. Inside the -- Maybe, there is a pair. The second element of the pair is our -- filter function FilterFun Response. -- FilterFun Response is a type alias for -- SetAppend (Dual (Endo Response)). -- This is just a wrapper for a Response -> -- Response function with a particular Monoid -- behavior. The value -- --
--   Append (Dual (Endo f))
--   
-- -- Causes f to be composed with the previous filter. -- --
--   Set (Dual (Endo f))
--   
-- -- Causes f to not be composed with the previous filter. -- -- Finally, the first element of the pair is either Left -- Response or Right a. -- -- Another way of looking at all these pieces is from the behaviors they -- control. The Maybe controls the mzero behavior. -- Set (Endo f) comes from the setFilter -- behavior. Likewise, Append (Endo f) is from -- composeFilter. Left Response is what you -- get when you call finishWith and Right a is the -- normal exit. -- -- An example case statement looks like: -- --
--   ex1 webt = do
--     val <- ununWebT webt
--     case val of
--         Nothing -> Nothing  -- this is the interior value when mzero was used
--         Just (Left r, f) -> Just (Left r, f) -- r is the value that was passed into "finishWith"
--                                              -- f is our filter function
--         Just (Right a, f) -> Just (Right a, f) -- a is our normal monadic value
--                                                -- f is still our filter function
--   
type UnWebT m a = m (Maybe (Either Response a, FilterFun Response)) -- | WebMonad provides a means to end the current computation and -- return a Response immediately. This provides an alternate -- escape route. In particular it has a monadic value of any type. And -- unless you call setFilter id first your -- response filters will be applied normally. -- -- Extremely useful when you're deep inside a monad and decide that you -- want to return a completely different content type, since it doesn't -- force you to convert all your return types to Response early -- just to accommodate this. -- -- see also: escape and escape' class Monad m => WebMonad a m | m -> a finishWith :: WebMonad a m => a -> m b -- | Used to ignore all your filters and immediately end the computation. A -- combination of ignoreFilters and finishWith. escape :: (WebMonad a m, FilterMonad a m) => m a -> m b -- | An alternate form of escape that can be easily used within a do -- block. escape' :: (WebMonad a m, FilterMonad a m) => a -> m b -- | For when you really need to unpack a WebT entirely (and not -- just unwrap the first layer with unWebT). ununWebT :: WebT m a -> UnWebT m a -- | For wrapping a WebT back up. mkWebT . -- ununWebT = id mkWebT :: UnWebT m a -> WebT m a -- | See mapServerPartT for a discussion of this function. mapWebT :: (UnWebT m a -> UnWebT n b) -> (WebT m a -> WebT n b) -- | This is kinda like a very oddly shaped mapServerPartT or -- mapWebT. You probably want one or the other of those. localContext :: Monad m => (WebT m a -> WebT m' a) -> ServerPartT m a -> ServerPartT m' a -- | Deprecated: use msum. -- | Deprecated: Use msum instead multi :: Monad m => [ServerPartT m a] -> ServerPartT m a -- | What is this for, exactly? I don't understand why Show a is -- even in the context Deprecated: This function appears to do nothing at -- all. If it use it, let us know why. -- | Deprecated: This function appears to do nothing. debugFilter :: (MonadIO m, Show a) => ServerPartT m a -> ServerPartT m a outputTraceMessage :: String -> a -> a mkFailMessage :: (FilterMonad Response m, WebMonad Response m) => String -> m b failHtml :: String -> String escapeString :: String -> String instance [overlap ok] Eq a => Eq (SetAppend a) instance [overlap ok] Show a => Show (SetAppend a) instance [overlap ok] Functor m => Functor (FilterT a m) instance [overlap ok] Applicative m => Applicative (FilterT a m) instance [overlap ok] Monad m => Monad (FilterT a m) instance [overlap ok] MonadTrans (FilterT a) instance [overlap ok] Functor m => Functor (WebT m) instance [overlap ok] Monad m => Monad (ServerPartT m) instance [overlap ok] Monad m => MonadPlus (ServerPartT m) instance [overlap ok] Functor m => Functor (ServerPartT m) instance [overlap ok] (WebMonad a m, Monoid w) => WebMonad a (RWST r w s m) instance [overlap ok] (FilterMonad res m, Monoid w) => FilterMonad res (RWST r w s m) instance [overlap ok] (ServerMonad m, Monoid w) => ServerMonad (RWST r w s m) instance [overlap ok] (WebMonad a m, Monoid w) => WebMonad a (WriterT w m) instance [overlap ok] (FilterMonad res m, Monoid w) => FilterMonad res (WriterT w m) instance [overlap ok] (ServerMonad m, Monoid w) => ServerMonad (WriterT w m) instance [overlap ok] WebMonad a m => WebMonad a (StateT s m) instance [overlap ok] FilterMonad res m => FilterMonad res (StateT s m) instance [overlap ok] ServerMonad m => ServerMonad (StateT s m) instance [overlap ok] WebMonad a m => WebMonad a (ReaderT r m) instance [overlap ok] FilterMonad res m => FilterMonad res (ReaderT r m) instance [overlap ok] ServerMonad m => ServerMonad (ReaderT r m) instance [overlap ok] MonadWriter w m => MonadWriter w (WebT m) instance [overlap ok] MonadError e m => MonadError e (WebT m) instance [overlap ok] MonadState st m => MonadState st (WebT m) instance [overlap ok] MonadReader r m => MonadReader r (WebT m) instance [overlap ok] (Functor m, MonadPlus m) => Alternative (WebT m) instance [overlap ok] (Monad m, Functor m) => Applicative (WebT m) instance [overlap ok] Monad m => Monoid (WebT m a) instance [overlap ok] Monad m => FilterMonad Response (WebT m) instance [overlap ok] Monad m => MonadPlus (WebT m) instance [overlap ok] MonadTrans WebT instance [overlap ok] Monad m => WebMonad Response (WebT m) instance [overlap ok] Monad m => Monad (WebT m) instance [overlap ok] MonadBaseControl b m => MonadBaseControl b (WebT m) instance [overlap ok] MonadTransControl WebT instance [overlap ok] MonadIO m => MonadIO (WebT m) instance [overlap ok] MonadBase b m => MonadBase b (WebT m) instance [overlap ok] Monad m => FilterMonad a (FilterT a m) instance [overlap ok] MonadBaseControl b m => MonadBaseControl b (FilterT a m) instance [overlap ok] MonadTransControl (FilterT a) instance [overlap ok] MonadIO m => MonadIO (FilterT a m) instance [overlap ok] MonadBase b m => MonadBase b (FilterT a m) instance [overlap ok] Functor SetAppend instance [overlap ok] Monoid a => Monoid (SetAppend a) instance [overlap ok] (Error e, ServerMonad m) => ServerMonad (ErrorT e m) instance [overlap ok] Monad m => ServerMonad (ServerPartT m) instance [overlap ok] Monad m => WebMonad Response (ServerPartT m) instance [overlap ok] Monad m => FilterMonad Response (ServerPartT m) instance [overlap ok] (Monad m, MonadState s m) => MonadState s (ServerPartT m) instance [overlap ok] (Monad m, MonadReader r m) => MonadReader r (ServerPartT m) instance [overlap ok] (Monad m, MonadError e m) => MonadError e (ServerPartT m) instance [overlap ok] (Monad m, MonadWriter w m) => MonadWriter w (ServerPartT m) instance [overlap ok] (Functor m, MonadPlus m) => Alternative (ServerPartT m) instance [overlap ok] (Monad m, Functor m) => Applicative (ServerPartT m) instance [overlap ok] Monad m => Monoid (ServerPartT m a) instance [overlap ok] MonadTrans ServerPartT instance [overlap ok] MonadBaseControl b m => MonadBaseControl b (ServerPartT m) instance [overlap ok] MonadTransControl ServerPartT instance [overlap ok] MonadIO m => MonadIO (ServerPartT m) instance [overlap ok] MonadBase b m => MonadBase b (ServerPartT m) -- | Functions for creating, adding, and expiring cookies. To lookup cookie -- values see Happstack.Server.RqData. module Happstack.Server.Cookie -- | a type for HTTP cookies. Usually created using mkCookie. data Cookie Cookie :: String -> String -> String -> String -> String -> Bool -> Bool -> Cookie cookieVersion :: Cookie -> String cookiePath :: Cookie -> String cookieDomain :: Cookie -> String cookieName :: Cookie -> String cookieValue :: Cookie -> String secure :: Cookie -> Bool httpOnly :: Cookie -> Bool -- | Specify the lifetime of a cookie. -- -- Note that we always set the max-age and expires headers because -- internet explorer does not honor max-age. You can specific -- MaxAge or Expires and the other will be calculated for -- you. Choose which ever one makes your life easiest. data CookieLife -- | session cookie - expires when browser is closed Session :: CookieLife -- | life time of cookie in seconds MaxAge :: Int -> CookieLife -- | cookie expiration date Expires :: UTCTime -> CookieLife -- | cookie already expired Expired :: CookieLife -- | Creates a cookie with a default version of 1, empty domain, a path of -- /, secure == False and httpOnly == False -- -- see also: addCookie mkCookie :: String -> String -> Cookie -- | Add the Cookie to Response. -- -- example -- --
--   main = simpleHTTP nullConf $
--     do addCookie Session (mkCookie "name" "value")
--        ok $ "You now have a session cookie."
--   
-- -- see also: addCookies addCookie :: (MonadIO m, FilterMonad Response m) => CookieLife -> Cookie -> m () -- | Add the list Cookie to the Response. -- -- see also: addCookie addCookies :: (MonadIO m, FilterMonad Response m) => [(CookieLife, Cookie)] -> m () -- | Expire the named cookie immediately and set the cookie value to -- "" -- --
--   main = simpleHTTP nullConf $
--     do expireCookie "name"
--        ok $ "The cookie has been expired."
--   
expireCookie :: (MonadIO m, FilterMonad Response m) => String -> m () -- | Functions and classes related to generating a Response and -- setting the response code. For detailed instruction see the Happstack -- Crash Course: -- http://happstack.com/docs/crashcourse/HelloWorld.html#response_code module Happstack.Server.Response -- | toResponse will convert a value into a Response body, -- set the content-type, and set the default response code for -- that type. -- -- happstack-server Example: -- --
--   main = simpleHTTP nullConf $ toResponse "hello, world!"
--   
-- -- will generate a Response with the content-type -- text/plain, the response code 200 OK, and the body: -- hello, world!. -- -- simpleHTTP will call toResponse automatically, so the -- above can be shortened to: -- --
--   main = simpleHTTP nullConf $ "hello, world!"
--   
-- -- happstack-lite Example: -- --
--   main = serve Nothing $ toResponse "hello, world!"
--   
-- -- Minimal definition: toMessage (and usually -- toContentType). class ToMessage a where toContentType _ = pack "text/plain" toMessage = error "Happstack.Server.SimpleHTTP.ToMessage.toMessage: Not defined" toResponse val = let bs = toMessage val res = Response 200 empty nullRsFlags bs Nothing in setHeaderBS (pack "Content-Type") (toContentType val) res toContentType :: ToMessage a => a -> ByteString toMessage :: ToMessage a => a -> ByteString toResponse :: ToMessage a => a -> Response -- | alias for: fmap toResponse -- -- turns m a into m Response using -- toResponse. -- --
--   main = simpleHTTP nullConf $ flatten $ do return "flatten me."
--   
flatten :: (ToMessage a, Functor f) => f a -> f Response -- | A low-level function to build a Response from a content-type -- and a ByteString. -- -- Creates a Response in a manner similar to the ToMessage -- class, but without requiring an instance declaration. -- -- example: -- --
--   import Data.ByteString.Char8 as C
--   import Data.ByteString.Lazy.Char8 as L
--   import Happstack.Server
--   
--   main = simpleHTTP nullConf $ ok $ toResponseBS (C.pack "text/plain") (L.pack "hello, world")
--   
-- -- (note: pack and pack only work for ascii. For unicode -- strings you would need to use utf8-string, text, or -- something similar to create a valid ByteString). toResponseBS :: ByteString -> ByteString -> Response -- | Respond with 200 OK. -- --
--   main = simpleHTTP nullConf $ ok "Everything is OK"
--   
ok :: FilterMonad Response m => a -> m a -- | Respond with 204 No Content -- -- A 204 No Content response may not contain a message-body. If -- you try to supply one, it will be dutifully ignored. -- --
--   main = simpleHTTP nullConf $ noContent "This will be ignored."
--   
noContent :: FilterMonad Response m => a -> m a -- | Respond with 500 Internal Server Error. -- --
--   main = simpleHTTP nullConf $ internalServerError "Sorry, there was an internal server error."
--   
internalServerError :: FilterMonad Response m => a -> m a -- | Responds with 502 Bad Gateway. -- --
--   main = simpleHTTP nullConf $ badGateway "Bad Gateway."
--   
badGateway :: FilterMonad Response m => a -> m a -- | Respond with 400 Bad Request. -- --
--   main = simpleHTTP nullConf $ badRequest "Bad Request."
--   
badRequest :: FilterMonad Response m => a -> m a -- | Respond with 401 Unauthorized. -- --
--   main = simpleHTTP nullConf $ unauthorized "You are not authorized."
--   
unauthorized :: FilterMonad Response m => a -> m a -- | Respond with 403 Forbidden. -- --
--   main = simpleHTTP nullConf $ forbidden "Sorry, it is forbidden."
--   
forbidden :: FilterMonad Response m => a -> m a -- | Respond with 404 Not Found. -- --
--   main = simpleHTTP nullConf $ notFound "What you are looking for has not been found."
--   
notFound :: FilterMonad Response m => a -> m a -- | A nicely formatted rendering of a Response prettyResponse :: Response -> String -- | Respond with 413 Request Entity Too Large. -- --
--   main = simpleHTTP nullConf $ requestEntityTooLarge "That's too big for me to handle."
--   
requestEntityTooLarge :: FilterMonad Response m => a -> m a -- | Respond with 303 See Other. -- --
--   main = simpleHTTP nullConf $ seeOther "http://example.org/" "What you are looking for is now at http://example.org/"
--   
-- -- NOTE: The second argument of seeOther is the message body which -- will sent to the browser. According to the HTTP 1.1 spec, -- --
--   the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).
--   
-- -- This is because pre-HTTP/1.1 user agents do not support 303. However, -- in practice you can probably just use "" as the second -- argument. seeOther :: (FilterMonad Response m, ToSURI uri) => uri -> res -> m res -- | Respond with 302 Found. -- -- You probably want seeOther. This method is not in popular use -- anymore, and is generally treated like 303 by most user-agents anyway. found :: (FilterMonad Response m, ToSURI uri) => uri -> res -> m res -- | Respond with 301 Moved Permanently. -- --
--   main = simpleHTTP nullConf $ movedPermanently "http://example.org/" "What you are looking for is now at http://example.org/"
--   
movedPermanently :: (FilterMonad Response m, ToSURI a) => a -> res -> m res -- | Respond with 307 Temporary Redirect. -- --
--   main = simpleHTTP nullConf $ tempRedirect "http://example.org/" "What you are looking for is temporarily at http://example.org/"
--   
tempRedirect :: (FilterMonad Response m, ToSURI a) => a -> res -> m res -- | Set an arbitrary return code in your response. -- -- A filter for setting the response code. Generally you will use a -- helper function like ok or seeOther. -- --
--   main = simpleHTTP nullConf $ do setResponseCode 200
--                                   return "Everything is OK"
--   
-- -- see also: resp setResponseCode :: FilterMonad Response m => Int -> m () -- | Same as setResponseCode status >> return val. -- -- Use this if you want to set a response code that does not already have -- a helper function. -- --
--   main = simpleHTTP nullConf $ resp 200 "Everything is OK"
--   
resp :: FilterMonad Response m => Int -> b -> m b -- | Honor an if-modified-since header in a Request. If the -- Request includes the if-modified-since header and the -- Response has not been modified, then return 304 (Not Modified), -- otherwise return the Response. ifModifiedSince :: UTCTime -> Request -> Response -> Response instance [overlap ok] ToMessage ByteString instance [overlap ok] ToMessage ByteString instance [overlap ok] ToMessage Response instance [overlap ok] ToMessage Html instance [overlap ok] ToMessage Html instance [overlap ok] ToMessage Html instance [overlap ok] ToMessage a => ToMessage (Maybe a) instance [overlap ok] ToMessage Integer instance [overlap ok] ToMessage Text instance [overlap ok] ToMessage Text instance [overlap ok] ToMessage String instance [overlap ok] ToMessage () -- | Functions for extracting values from the query string, form data, -- cookies, etc. -- -- For in-depth documentation see the following section of the Happstack -- Crash Course: -- -- http://happstack.com/docs/crashcourse/RqData.html module Happstack.Server.RqData -- | Gets the first matching named input parameter as a String -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- Example: -- --
--   handler :: ServerPart Response
--   handler =
--        do foo <- look "foo"
--           ok $ toResponse $ "foo = " ++ foo
--   
-- -- see also: looks, lookBS, and lookBSs look :: (Functor m, Monad m, HasRqData m) => String -> m String -- | Gets all matches for the named input parameter as Strings -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: look and lookBSs looks :: (Functor m, Monad m, HasRqData m) => String -> m [String] -- | Gets the first matching named input parameter as a lazy Text -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookTexts, look, looks, lookBS, -- and lookBSs lookText :: (Functor m, Monad m, HasRqData m) => String -> m Text -- | Gets the first matching named input parameter as a strict Text -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookTexts, look, looks, lookBS, -- and lookBSs lookText' :: (Functor m, Monad m, HasRqData m) => String -> m Text -- | Gets all matches for the named input parameter as lazy Texts -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookText, looks and lookBSs lookTexts :: (Functor m, Monad m, HasRqData m) => String -> m [Text] -- | Gets all matches for the named input parameter as strict Texts -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookText', looks and lookBSs lookTexts' :: (Functor m, Monad m, HasRqData m) => String -> m [Text] -- | Gets the first matching named input parameter as a lazy -- ByteString -- -- Searches the QUERY_STRING followed by the Request body. -- -- see also: lookBSs lookBS :: (Functor m, Monad m, HasRqData m) => String -> m ByteString -- | Gets all matches for the named input parameter as lazy -- ByteStrings -- -- Searches the QUERY_STRING followed by the Request body. -- -- see also: lookBS lookBSs :: (Functor m, Monad m, HasRqData m) => String -> m [ByteString] -- | Gets the first matching named input parameter and decodes it using -- Read -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookReads lookRead :: (Functor m, Monad m, HasRqData m, FromReqURI a) => String -> m a -- | Gets all matches for the named input parameter and decodes them using -- Read -- -- Searches the QUERY_STRING followed by the Request body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookReads lookReads :: (Functor m, Monad m, HasRqData m, FromReqURI a) => String -> m [a] -- | Gets the first matching named file -- -- Files can only appear in the request body. Additionally, the form must -- set enctype="multipart/form-data". -- -- This function returns a tuple consisting of: -- --
    --
  1. The temporary location of the uploaded file
  2. --
  3. The local filename supplied by the browser
  4. --
  5. The content-type supplied by the browser
  6. --
-- -- If the user does not supply a file in the html form input field, the -- behaviour will depend upon the browser. Most browsers will send a -- 0-length file with an empty file name, so checking that (2) is not -- empty is usually sufficient to ensure the field has been filled. -- -- NOTE: You must move the file from the temporary location before the -- Response is sent. The temporary files are automatically removed -- after the Response is sent. lookFile :: (Monad m, HasRqData m) => String -> m (FilePath, FilePath, ContentType) -- | gets all the input parameters, and converts them to a String -- -- The results will contain the QUERY_STRING followed by the Request -- body. -- -- This function assumes the underlying octets are UTF-8 encoded. -- -- see also: lookPairsBS lookPairs :: (Monad m, HasRqData m) => m [(String, Either FilePath String)] -- | gets all the input parameters -- -- The results will contain the QUERY_STRING followed by the Request -- body. -- -- see also: lookPairs lookPairsBS :: (Monad m, HasRqData m) => m [(String, Either FilePath ByteString)] -- | Gets the named cookie the cookie name is case insensitive lookCookie :: (Monad m, HasRqData m) => String -> m Cookie -- | gets the named cookie as a string lookCookieValue :: (Functor m, Monad m, HasRqData m) => String -> m String -- | gets the named cookie as the requested Read type readCookieValue :: (Functor m, Monad m, HasRqData m, FromReqURI a) => String -> m a -- | Gets the first matching named input parameter -- -- Searches the QUERY_STRING followed by the Request body. -- -- see also: lookInputs lookInput :: (Monad m, HasRqData m) => String -> m Input -- | Gets all matches for the named input parameter -- -- Searches the QUERY_STRING followed by the Request body. -- -- see also: lookInput lookInputs :: (Monad m, HasRqData m) => String -> m [Input] -- | limit the scope to the Request body -- --
--   handler :: ServerPart Response
--   handler =
--       do foo <- body $ look "foo"
--          ok $ toResponse $ "foo = " ++ foo
--   
body :: HasRqData m => m a -> m a -- | limit the scope to the QUERY_STRING -- --
--   handler :: ServerPart Response
--   handler =
--       do foo <- queryString $ look "foo"
--          ok $ toResponse $ "foo = " ++ foo
--   
queryString :: HasRqData m => m a -> m a -- | limit the scope to Inputs which produce a ByteString -- (aka, not a file) bytestring :: HasRqData m => m a -> m a -- | convert or validate a value -- -- This is similar to fmap except that the function can fail by -- returning Left and an error message. The error will be propagated by -- calling rqDataError. -- -- This function is useful for a number of things including: -- --
    --
  1. Parsing a String into another type
  2. --
  3. Checking that a value meets some requirements (for example, that -- is an Int between 1 and 10).
  4. --
-- -- Example usage at: -- -- http://happstack.com/docs/crashcourse/RqData.html#rqdatacheckrq checkRq :: (Monad m, HasRqData m) => m a -> (a -> Either String b) -> m b -- | like checkRq but the check function can be monadic checkRqM :: (Monad m, HasRqData m) => m a -> (a -> m (Either String b)) -> m b -- | use fromReqURI to convert a String to a value of type -- a -- --
--   look "key" `checkRq` (readRq "key")
--   
-- -- use with checkRq readRq :: FromReqURI a => String -> String -> Either String a -- | use read to convert a String to a value of type -- a -- --
--   look "key" `checkRq` (unsafeReadRq "key")
--   
-- -- use with checkRq -- -- NOTE: This function is marked unsafe because some Read instances are -- vulnerable to attacks that attempt to create an out of memory -- condition. For example: -- --
--   read "1e10000000000000" :: Integer
--   
-- -- see also: readRq unsafeReadRq :: Read a => String -> String -> Either String a -- | The POST/PUT body of a Request is not received or decoded unless this -- function is invoked. -- -- It is an error to try to use the look functions for a POST/PUT request -- with out first calling this function. -- -- It is ok to call decodeBody at the beginning of every request: -- --
--   main = simpleHTTP nullConf $ 
--             do decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096)
--                handlers
--   
-- -- You can achieve finer granularity quotas by calling decodeBody -- with different values in different handlers. -- -- Only the first call to decodeBody will have any effect. Calling -- it a second time, even with different quota values, will do nothing. decodeBody :: (ServerMonad m, MonadPlus m, MonadIO m, FilterMonad Response m, WebMonad Response m) => BodyPolicy -> m () -- | see defaultBodyPolicy data BodyPolicy BodyPolicy :: (Int64 -> Int64 -> Int64 -> InputWorker) -> Int64 -> Int64 -> Int64 -> BodyPolicy inputWorker :: BodyPolicy -> Int64 -> Int64 -> Int64 -> InputWorker -- | maximum bytes for files uploaded in this Request maxDisk :: BodyPolicy -> Int64 -- | maximum bytes for all non-file values in the Request body maxRAM :: BodyPolicy -> Int64 -- | maximum bytes of overhead for headers in multipart/form-data maxHeader :: BodyPolicy -> Int64 -- | create a BodyPolicy for use with decodeBody defaultBodyPolicy :: FilePath -> Int64 -> Int64 -> Int64 -> BodyPolicy -- | An applicative functor and monad for looking up key/value pairs in the -- QUERY_STRING, Request body, and cookies. data RqData a -- | transform the result of 'RqData a'. -- -- This is similar to fmap except it also allows you to modify the -- Errors not just a. mapRqData :: (Either (Errors String) a -> Either (Errors String) b) -> RqData a -> RqData b -- | a list of errors newtype Errors a Errors :: [a] -> Errors a unErrors :: Errors a -> [a] -- | run RqData in a ServerMonad. -- -- Example: a simple GET or POST variable based -- authentication guard. It handles the request with -- errorHandler if authentication fails. -- --
--   data AuthCredentials = AuthCredentials { username :: String,  password :: String }
--   
--   isValid :: AuthCredentials -> Bool
--   isValid = const True
--   
--   myRqData :: RqData AuthCredentials
--   myRqData = do
--      username <- look "username"
--      password <- look "password"
--      return (AuthCredentials username password)
--   
--   checkAuth :: (String -> ServerPart Response) -> ServerPart Response
--   checkAuth errorHandler = do
--      d <- getDataFn myRqData
--      case d of
--          (Left e) -> errorHandler (unlines e)
--          (Right a) | isValid a -> mzero
--          (Right a) | otherwise -> errorHandler "invalid"
--   
-- -- NOTE: you must call decodeBody prior to calling this function -- if the request method is POST or PUT. getDataFn :: (HasRqData m, ServerMonad m) => RqData a -> m (Either [String] a) -- | similar to getDataFn, except it calls a sub-handler on success -- or mzero on failure. -- -- NOTE: you must call decodeBody prior to calling this function -- if the request method is POST or PUT. withDataFn :: (HasRqData m, MonadPlus m, ServerMonad m) => RqData a -> (a -> m r) -> m r -- | Used by withData and getData. Make your preferred data -- type an instance of FromData to use those functions. class FromData a fromData :: FromData a => RqData a -- | A variant of getDataFn that uses FromData to chose your -- RqData for you. The example from getData becomes: -- --
--   data AuthCredentials = AuthCredentials { username :: String,  password :: String }
--   
--   isValid :: AuthCredentials -> Bool
--   isValid = const True
--   
--   myRqData :: RqData AuthCredentials
--   myRqData = do
--      username <- look "username"
--      password <- look "password"
--      return (AuthCredentials username password)
--   
--   instance FromData AuthCredentials where
--      fromData = myRqData
--   
--   checkAuth :: (String -> ServerPart Response) -> ServerPart Response
--   checkAuth errorHandler = do
--      d <- getData
--      case d of
--          (Left e) -> errorHandler (unlines e)
--          (Right a) | isValid a -> mzero
--          (Right a) | otherwise -> errorHandler "invalid"
--   
-- -- NOTE: you must call decodeBody prior to calling this function -- if the request method is POST or PUT. getData :: (HasRqData m, ServerMonad m, FromData a) => m (Either [String] a) -- | similar to getData except it calls a subhandler on success or -- mzero on failure. -- -- NOTE: you must call decodeBody prior to calling this function -- if the request method is POST or PUT. withData :: (HasRqData m, FromData a, MonadPlus m, ServerMonad m) => (a -> m r) -> m r -- | the environment used to lookup query parameters. It consists of the -- triple: (query string inputs, body inputs, cookie inputs) type RqEnv = ([(String, Input)], Maybe [(String, Input)], [(String, Cookie)]) -- | A class for monads which contain a RqEnv class HasRqData m askRqEnv :: HasRqData m => m RqEnv localRqEnv :: HasRqData m => (RqEnv -> RqEnv) -> m a -> m a rqDataError :: HasRqData m => Errors String -> m a instance [overlap ok] Typeable1 Errors instance [overlap ok] Functor (ReaderError r e) instance [overlap ok] Monad (ReaderError r e) instance [overlap ok] Error e => MonadPlus (ReaderError r e) instance [overlap ok] Eq a => Eq (Errors a) instance [overlap ok] Ord a => Ord (Errors a) instance [overlap ok] Show a => Show (Errors a) instance [overlap ok] Read a => Read (Errors a) instance [overlap ok] Data a => Data (Errors a) instance [overlap ok] Functor RqData instance [overlap ok] Monad RqData instance [overlap ok] MonadPlus RqData instance [overlap ok] Applicative RqData instance [overlap ok] Alternative RqData instance [overlap ok] MonadReader RqEnv RqData instance [overlap ok] FromData a => FromData (Maybe a) instance [overlap ok] (FromData a, FromData b, FromData c, FromData d) => FromData (a, b, c, d) instance [overlap ok] (FromData a, FromData b, FromData c) => FromData (a, b, c) instance [overlap ok] (FromData a, FromData b) => FromData (a, b) instance [overlap ok] (Monad m, HasRqData m, Monoid w) => HasRqData (RWST r w s m) instance [overlap ok] (Monad m, HasRqData m, Monoid w) => HasRqData (WriterT w m) instance [overlap ok] (Monad m, HasRqData m) => HasRqData (StateT s m) instance [overlap ok] (Monad m, HasRqData m) => HasRqData (ReaderT s m) instance [overlap ok] MonadIO m => HasRqData (ServerPartT m) instance [overlap ok] HasRqData RqData instance [overlap ok] Error (Errors String) instance [overlap ok] Monoid (Errors a) instance [overlap ok] (Monoid e, Error e) => Alternative (ReaderError r e) instance [overlap ok] (Monoid e, Error e) => Applicative (ReaderError r e) instance [overlap ok] Error e => MonadReader r (ReaderError r e) -- | This module provides four classes and some related functions which -- provide ServerPartT with much of its web-centric behavior. -- --
    --
  1. ServerMonad provides access to the HTTP -- Request
  2. --
  3. FilterMonad provides the ability to apply filters and -- transformations to a Response
  4. --
  5. WebMonad provides a way to escape a computation early and -- return a Response
  6. --
  7. HasRqData which provides access to the decoded QUERY_STRING -- and request body/form data
  8. --
module Happstack.Server.Monads -- | ServerPartT is a rich, featureful monad for web development. -- -- see also: simpleHTTP, ServerMonad, FilterMonad, -- WebMonad, and HasRqData data ServerPartT m a -- | An alias for ServerPartT IO type ServerPart a = ServerPartT IO a -- | A class alias for all the classes a standard server monad (such as -- ServerPartT) is expected to have instances for. This allows you -- to keep your type signatures shorter and easier to understand. class (ServerMonad m, WebMonad Response m, FilterMonad Response m, MonadIO m, MonadPlus m, HasRqData m, Monad m, Functor m, Applicative m, Alternative m) => Happstack m -- | The ServerMonad class provides methods for reading or locally -- modifying the Request. It is essentially a specialized version -- of the MonadReader class. Providing the unique names, -- askRq and localRq makes it easier to use -- ServerPartT and ReaderT together. class Monad m => ServerMonad m askRq :: ServerMonad m => m Request localRq :: ServerMonad m => (Request -> Request) -> m a -> m a -- | Apply a function to transform the inner monad of -- ServerPartT m. -- -- Often used when transforming a monad with ServerPartT, since -- simpleHTTP requires a ServerPartT IO -- a. Refer to UnWebT for an explanation of the structure of -- the monad. -- -- Here is an example. Suppose you want to embed an ErrorT into -- your ServerPartT to enable throwError and -- catchError in your Monad. -- --
--   type MyServerPartT e m a = ServerPartT (ErrorT e m) a
--   
-- -- Now suppose you want to pass MyServerPartT into a function -- that demands a ServerPartT IO a (e.g. -- simpleHTTP). You can provide the function: -- --
--   unpackErrorT :: (Monad m, Show e) => UnWebT (ErrorT e m) a -> UnWebT m a
--   unpackErrorT et = do
--      eitherV <- runErrorT et
--      return $ case eitherV of
--          Left err -> Just (Left $ toResponse $
--                                   "Catastrophic failure " ++ show err
--                           , filterFun $ \r -> r{rsCode = 500})
--          Right x -> x
--   
-- -- With unpackErrorT you can now call simpleHTTP. Just -- wrap your ServerPartT list. -- --
--   simpleHTTP nullConf $ mapServerPartT unpackErrorT (myPart `catchError` myHandler)
--   
-- -- Or alternatively: -- --
--   simpleHTTP' unpackErrorT nullConf (myPart `catchError` myHandler)
--   
-- -- Also see spUnwrapErrorT for a more sophisticated version of -- this function. mapServerPartT :: (UnWebT m a -> UnWebT n b) -> (ServerPartT m a -> ServerPartT n b) -- | A variant of mapServerPartT where the first argument also takes -- a Request. Useful if you want to runServerPartT on a -- different ServerPartT inside your monad (see -- spUnwrapErrorT). mapServerPartT' :: (Request -> UnWebT m a -> UnWebT n b) -> (ServerPartT m a -> ServerPartT n b) -- | UnWebT is almost exclusively used with mapServerPartT. -- If you are not using mapServerPartT then you do not need to -- wrap your head around this type. If you are -- the type is not as -- complex as it first appears. -- -- It is worth discussing the unpacked structure of WebT a bit as -- it's exposed in mapServerPartT and mapWebT. -- -- A fully unpacked WebT has a structure that looks like: -- --
--   ununWebT $ WebT m a :: m (Maybe (Either Response a, FilterFun Response))
--   
-- -- So, ignoring m, as it is just the containing Monad, -- the outermost layer is a Maybe. This is Nothing if -- mzero was called or Just (Either -- Response a, SetAppend (Endo -- Response)) if mzero wasn't called. Inside the -- Maybe, there is a pair. The second element of the pair is our -- filter function FilterFun Response. -- FilterFun Response is a type alias for -- SetAppend (Dual (Endo Response)). -- This is just a wrapper for a Response -> -- Response function with a particular Monoid -- behavior. The value -- --
--   Append (Dual (Endo f))
--   
-- -- Causes f to be composed with the previous filter. -- --
--   Set (Dual (Endo f))
--   
-- -- Causes f to not be composed with the previous filter. -- -- Finally, the first element of the pair is either Left -- Response or Right a. -- -- Another way of looking at all these pieces is from the behaviors they -- control. The Maybe controls the mzero behavior. -- Set (Endo f) comes from the setFilter -- behavior. Likewise, Append (Endo f) is from -- composeFilter. Left Response is what you -- get when you call finishWith and Right a is the -- normal exit. -- -- An example case statement looks like: -- --
--   ex1 webt = do
--     val <- ununWebT webt
--     case val of
--         Nothing -> Nothing  -- this is the interior value when mzero was used
--         Just (Left r, f) -> Just (Left r, f) -- r is the value that was passed into "finishWith"
--                                              -- f is our filter function
--         Just (Right a, f) -> Just (Right a, f) -- a is our normal monadic value
--                                                -- f is still our filter function
--   
type UnWebT m a = m (Maybe (Either Response a, FilterFun Response)) -- | turn a function into a FilterFun. Primarily used with -- mapServerPartT filterFun :: (a -> a) -> FilterFun a -- | A set of functions for manipulating filters. -- -- ServerPartT implements FilterMonad Response so -- these methods are the fundamental ways of manipulating Response -- values. class Monad m => FilterMonad a m | m -> a setFilter :: FilterMonad a m => (a -> a) -> m () composeFilter :: FilterMonad a m => (a -> a) -> m () getFilter :: FilterMonad a m => m b -> m (b, a -> a) -- | Resets all your filters. An alias for setFilter -- id. ignoreFilters :: FilterMonad a m => m () -- | Add headers into the response. This method does not overwrite any -- existing header of the same name, hence the name addHeaderM. If -- you want to replace a header use setHeaderM. addHeaderM :: FilterMonad Response m => String -> String -> m () -- | Get a header out of the request. getHeaderM :: ServerMonad m => String -> m (Maybe ByteString) -- | Set a header into the response. This will replace an existing header -- of the same name. Use addHeaderM if you want to add more than -- one header of the same name. setHeaderM :: FilterMonad Response m => String -> String -> m () -- | Set a far-future Expires header. Useful for static resources. If the -- browser has the resource cached, no extra request is spent. neverExpires :: FilterMonad Response m => m () -- | WebMonad provides a means to end the current computation and -- return a Response immediately. This provides an alternate -- escape route. In particular it has a monadic value of any type. And -- unless you call setFilter id first your -- response filters will be applied normally. -- -- Extremely useful when you're deep inside a monad and decide that you -- want to return a completely different content type, since it doesn't -- force you to convert all your return types to Response early -- just to accommodate this. -- -- see also: escape and escape' class Monad m => WebMonad a m | m -> a finishWith :: WebMonad a m => a -> m b -- | Used to ignore all your filters and immediately end the computation. A -- combination of ignoreFilters and finishWith. escape :: (WebMonad a m, FilterMonad a m) => m a -> m b -- | An alternate form of escape that can be easily used within a do -- block. escape' :: (WebMonad a m, FilterMonad a m) => a -> m b -- | Run an IO action and, if it returns Just, pass it to the -- second argument. require :: (MonadIO m, MonadPlus m) => IO (Maybe a) -> (a -> m r) -> m r -- | A variant of require that can run in any monad, not just IO. requireM :: (MonadTrans t, Monad m, MonadPlus (t m)) => m (Maybe a) -> (a -> t m r) -> t m r instance [overlap ok] (Happstack m, Monoid w) => Happstack (RWST r w s m) instance [overlap ok] (Happstack m, Monoid w) => Happstack (WriterT w m) instance [overlap ok] Happstack m => Happstack (ReaderT r m) instance [overlap ok] Happstack m => Happstack (StateT s m) instance [overlap ok] (Functor m, Monad m, MonadPlus m, MonadIO m) => Happstack (ServerPartT m) -- | Support for basic access authentication -- http://en.wikipedia.org/wiki/Basic_access_authentication module Happstack.Server.Auth -- | A simple HTTP basic authentication guard. -- -- If authentication fails, this part will call mzero. -- -- example: -- --
--   main = simpleHTTP nullConf $ 
--    msum [ basicAuth "127.0.0.1" (fromList [("happstack","rocks")]) $ ok "You are in the secret club"
--         , ok "You are not in the secret club." 
--         ]
--   
basicAuth :: Happstack m => String -> Map String String -> m a -> m a -- | Some useful functions if you want to wrap the ServerPartT monad -- transformer around the ErrorT monad transformer. e.g., -- ServerPartT (ErrorT e m) a. This allows you to -- use throwError and catchError inside your monad. module Happstack.Server.Error -- | Flatten ServerPartT (ErrorT e m) a into a -- ServerPartT m a so that it can be use with -- simpleHTTP. Used with mapServerPartT', e.g., -- --
--   simpleHTTP conf $ mapServerPartT' (spUnWrapErrorT simpleErrorHandler)  $ myPart `catchError` errorPart
--   
-- -- Note that in this example, simpleErrorHandler will only be -- run if errorPart throws an error. You can replace -- simpleErrorHandler with your own custom error handler. -- -- see also: simpleErrorHandler spUnwrapErrorT :: Monad m => (e -> ServerPartT m a) -> Request -> UnWebT (ErrorT e m) a -> UnWebT m a -- | A simple error handler which can be used with spUnwrapErrorT. -- -- It returns the error message as a plain text message to the browser. -- More sophisticated behaviour can be achieved by calling your own -- custom error handler instead. -- -- see also: spUnwrapErrorT simpleErrorHandler :: Monad m => String -> ServerPartT m Response -- | This ServerPart modifier enables the use of -- throwError and catchError inside the WebT -- actions, by adding the ErrorT monad transformer to the stack. -- -- You can wrap the complete second argument to simpleHTTP in -- this function. -- -- DEPRECATED: use spUnwrapErrorT instead. -- | Deprecated: Use spUnwrapErrorT errorHandlerSP :: (Monad m, Error e) => (Request -> e -> WebT m a) -> ServerPartT (ErrorT e m) a -> ServerPartT m a -- | Support for creating a proxy or reverse-proxy server module Happstack.Server.Proxy -- | proxyServe is for creating a part that acts as a proxy. The -- sole argument [String] is a list of allowed domains -- for proxying. This matches the domain part of the request and the -- wildcard * can be used. E.g. -- -- -- -- TODO: annoyingly enough, this method eventually calls escape, -- so any headers you set won't be used, and the computation immediately -- ends. proxyServe :: (MonadIO m, WebMonad Response m, ServerMonad m, MonadPlus m, FilterMonad Response m) => [String] -> m Response -- | Take a proxy Request and create a Response. Your basic -- proxy building block. See unproxify. -- -- TODO: this would be more useful if it didn't call escape -- (e.g. it let you modify the response afterwards, or set additional -- headers) proxyServe' :: (MonadIO m, FilterMonad Response m, WebMonad Response m) => Request -> m Response -- | This is a reverse proxy implementation. See unrproxify. -- -- TODO: this would be more useful if it didn't call escape, -- just like proxyServe'. rproxyServe :: (ServerMonad m, WebMonad Response m, FilterMonad Response m, MonadIO m) => String -> [(String, String)] -> m Response unproxify :: Request -> Request unrproxify :: String -> [(String, String)] -> Request -> Request -- | Support for validating server output on-the-fly. Validators can be -- configured on a per content-type basis. module Happstack.Server.Validation -- | Set the validator which should be used for this particular -- Response when validation is enabled. -- -- Calling this function does not enable validation. That can only be -- done by enabling the validation in the Conf that is passed to -- simpleHTTP. -- -- You do not need to call this function if the validator set in -- Conf does what you want already. -- -- Example: (use noopValidator instead of the default supplied by -- validateConf) -- --
--   simpleHTTP validateConf $ ok . setValidator noopValidator =<< htmlPage
--   
-- -- See also: validateConf, wdgHTMLValidator, -- noopValidator, lazyProcValidator. setValidator :: (Response -> IO Response) -> Response -> Response -- | ServerPart version of setValidator. -- -- Example: (Set validator to noopValidator) -- --
--   simpleHTTP validateConf $ setValidatorSP noopValidator (dir "ajax" ... )
--   
setValidatorSP :: (Monad m, ToMessage r) => (Response -> IO Response) -> m r -> m Response -- | Extend nullConf by enabling validation and setting -- wdgHTMLValidator as the default validator for -- text/html. -- -- Example: -- --
--   simpleHTTP validateConf . anyRequest $ ok htmlPage
--   
validateConf :: Conf -- | Actually perform the validation on a Response. -- -- Run the validator specified in the Response. If none is provide -- use the supplied default instead. -- -- Note: This function will run validation unconditionally. You probably -- want setValidator or validateConf. runValidator :: (Response -> IO Response) -> Response -> IO Response -- | Validate text/html content with WDG HTML Validator. -- -- This function expects the executable to be named validate and -- it must be in the default PATH. -- -- See also: setValidator, validateConf, -- lazyProcValidator. wdgHTMLValidator :: (MonadIO m, ToMessage r) => r -> m Response -- | A validator which always succeeds. -- -- Useful for selectively disabling validation. For example, if you are -- sending down HTML fragments to an AJAX application and the default -- validator only understands complete documents. noopValidator :: Response -> IO Response -- | Validate the Response using an external application. -- -- If the external application returns 0, the original response is -- returned unmodified. If the external application returns non-zero, a -- Response containing the error messages and original response -- body is returned instead. -- -- This function also takes a predicate filter which is applied to the -- content-type of the response. The filter will only be applied if the -- predicate returns true. -- -- NOTE: This function requires the use of -threaded to avoid blocking. -- However, you probably need that for Happstack anyway. -- -- See also: wdgHTMLValidator. lazyProcValidator :: FilePath -> [String] -> Maybe FilePath -> Maybe [(String, String)] -> (Maybe ByteString -> Bool) -> Response -> IO Response -- | Build your own file serving functions -- -- If the functions in Happstack.Server.FileServe do not quite do -- you want you can roll your own by reusing pieces from this module. -- -- You will likely want to start by copying the source for a function -- like, serveDirectory and then modifying it to suit your needs. module Happstack.Server.FileServe.BuildingBlocks -- | Serve files from a directory and its subdirectories using -- sendFile. -- -- Usage: -- --
--   fileServe ["index.html"] "path/to/files/on/disk"
--   
-- -- fileServe does not support directory browsing. See -- serveDirectory -- -- DEPRECATED: use serveDirectory instead. -- -- Note: -- -- The list of index files ["index.html"] is only used to -- determine what file to show if the user requests a directory. You *do -- not* need to explicitly list all the files you want to serve. -- | Deprecated: use serveDirectory instead. fileServe :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [FilePath] -> FilePath -> m Response -- | Serve files from a directory and its subdirectories (parameterizable -- version) -- -- Parameterize this function to create functions like, fileServe, -- fileServeLazy, and fileServeStrict -- -- You supply: -- --
    --
  1. a low-level function which takes a content-type and -- FilePath and generates a Response
  2. --
  3. a function which determines the content-type from the -- FilePath
  4. --
  5. a list of all the default index files
  6. --
-- -- NOTE: unlike fileServe, there are no index files by default. See -- defaultIxFiles. fileServe' :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => (String -> FilePath -> m Response) -> (FilePath -> m String) -> (FilePath -> m Response) -> FilePath -> m Response -- | Serve files from a directory and its subdirectories (lazy ByteString -- version). -- -- WARNING: May leak file handles. You should probably use -- fileServe instead. fileServeLazy :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [FilePath] -> FilePath -> m Response -- | Serve files from a directory and its subdirectories (strict ByteString -- version). -- -- WARNING: the entire file will be read into RAM before being served. -- You should probably use fileServe instead. fileServeStrict :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [FilePath] -> FilePath -> m Response -- | see serveDirectory data Browsing EnableBrowsing :: Browsing DisableBrowsing :: Browsing -- | Serve files and directories from a directory and its subdirectories -- using sendFile. -- -- Usage: -- --
--   serveDirectory EnableBrowsing ["index.html"] "path/to/files/on/disk"
--   
-- -- If the requested path does not match a file or directory on the disk, -- then serveDirectory calls mzero. -- -- If the requested path is a file then the file is served normally. -- -- If the requested path is a directory, then the result depends on what -- the first two arguments to the function are. -- -- The first argument controls whether directory browsing is enabled. -- -- The second argument is a list of index files (such as index.html). -- -- When a directory is requested, serveDirectory will first try to -- find one of the index files (in the order they are listed). If that -- fails, it will show a directory listing if EnableBrowsing is -- set, otherwise it will return forbidden "Directory index -- forbidden". -- -- Here is an explicit list of all the possible outcomes when the -- argument is a (valid) directory: -- -- -- -- This will always return, forbidden "Directory index forbidden" -- -- -- --
    --
  1. If an index file is found it will be shown.
  2. --
  3. Otherwise returns, forbidden "Directory index forbidden"
  4. --
-- -- -- -- Always shows a directory index. -- -- -- --
    --
  1. If an index file is found it will be shown
  2. --
  3. Otherwise shows a directory index
  4. --
-- -- see also: defaultIxFiles, serveFile serveDirectory :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => Browsing -> [FilePath] -> FilePath -> m Response -- | like serveDirectory but with custom mimeTypes serveDirectory' :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => Browsing -> [FilePath] -> (FilePath -> m String) -> FilePath -> m Response -- | Serve a single, specified file. The name of the file being served is -- specified explicity. It is not derived automatically from the -- Request url. -- -- example 1: -- -- Serve as a specific content-type: -- --
--   serveFile (asContentType "image/jpeg") "/srv/data/image.jpg"
--   
-- -- example 2: -- -- Serve guessing the content-type from the extension: -- --
--   serveFile (guessContentTypeM mimeTypes) "/srv/data/image.jpg"
--   
-- -- If the specified path does not exist or is not a file, this function -- will return mzero. -- -- WARNING: No security checks are performed. -- -- NOTE: alias for serveFileUsing filePathSendFile serveFile :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => (FilePath -> m String) -> FilePath -> m Response -- | Like serveFile, but uses combineSafe to prevent -- directory traversal attacks when the path to the file is supplied by -- the user. serveFileFrom :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => FilePath -> (FilePath -> m String) -> FilePath -> m Response -- | Serve a single, specified file. The name of the file being served is -- specified explicity. It is not derived automatically from the -- Request url. -- -- example 1: -- -- Serve using sendfile() and the specified content-type -- --
--   serveFileUsing filePathSendFile (asContentType "image/jpeg") "/srv/data/image.jpg"
--   
-- -- example 2: -- -- Serve using a lazy ByteString and the guess the content-type from the -- extension -- --
--   serveFileUsing filePathLazy (guessContentTypeM mimeTypes) "/srv/data/image.jpg"
--   
-- -- WARNING: No security checks are performed. serveFileUsing :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => (String -> FilePath -> m Response) -> (FilePath -> m String) -> FilePath -> m Response -- | Use sendFile to send the contents of a Handle sendFileResponse :: String -> FilePath -> Maybe (UTCTime, Request) -> Integer -> Integer -> Response -- | Send the contents of a Lazy ByteString lazyByteStringResponse :: String -> ByteString -> Maybe (UTCTime, Request) -> Integer -> Integer -> Response -- | Send the contents of a Lazy ByteString strictByteStringResponse :: String -> ByteString -> Maybe (UTCTime, Request) -> Integer -> Integer -> Response -- | Send the specified file with the specified mime-type using sendFile() -- -- NOTE: assumes file exists and is readable by the server. See -- serveFileUsing. -- -- WARNING: No security checks are performed. filePathSendFile :: (ServerMonad m, MonadIO m) => String -> FilePath -> m Response -- | Send the specified file with the specified mime-type using lazy -- ByteStrings -- -- NOTE: assumes file exists and is readable by the server. See -- serveFileUsing. -- -- WARNING: No security checks are performed. filePathLazy :: (ServerMonad m, MonadIO m) => String -> FilePath -> m Response -- | Send the specified file with the specified mime-type using strict -- ByteStrings -- -- NOTE: assumes file exists and is readable by the server. See -- serveFileUsing. -- -- WARNING: No security checks are performed. filePathStrict :: (ServerMonad m, MonadIO m) => String -> FilePath -> m Response -- | a Map from file extensions to content-types -- -- example: -- --
--   myMimeMap :: MimeMap
--   myMimeMap = Map.fromList [("gz","application/x-gzip"), ... ]
--   
-- -- see also: mimeTypes type MimeMap = Map String String -- | Ready collection of common mime types. Except for the first two -- entries, the mappings come from an Ubuntu 8.04 /etc/mime.types file. mimeTypes :: MimeMap -- | returns a specific content type, completely ignoring the -- FilePath argument. -- -- Use this with serveFile if you want to explicitly specify the -- content-type. -- -- see also: guessContentTypeM, serveFile asContentType :: Monad m => String -> (FilePath -> m String) -- | try to guess the content-type of a file based on its extension -- -- see also: guessContentTypeM guessContentType :: MimeMap -> FilePath -> Maybe String -- | try to guess the content-type of a file based on its extension -- -- defaults to application/octet-stream if no match was found. -- -- Useful as an argument to serveFile -- -- see also: guessContentType, serveFile guessContentTypeM :: Monad m => MimeMap -> (FilePath -> m String) data EntryKind File :: EntryKind Directory :: EntryKind UnknownKind :: EntryKind browseIndex :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m, ToMessage b) => (FilePath -> [FilePath] -> m b) -> (String -> FilePath -> m Response) -> (FilePath -> m String) -> [String] -> FilePath -> m Response -- | a function to generate an HTML page showing the contents of a -- directory on the disk -- -- see also: browseIndex, renderDirectoryContentsTable renderDirectoryContents :: MonadIO m => FilePath -> [FilePath] -> m Html -- | a function to generate an HTML table showing the contents of a -- directory on the disk -- -- This function generates most of the content of the -- renderDirectoryContents page. If you want to style the page -- differently, or add google analytics code, etc, you can just create a -- new page template to wrap around this HTML. -- -- see also: getMetaData, renderDirectoryContents renderDirectoryContentsTable :: [(FilePath, Maybe UTCTime, Maybe Integer, EntryKind)] -> Html -- | Prevents files of the form '.foo' or 'bar/.foo' from being served blockDotFiles :: (Request -> IO Response) -> Request -> IO Response -- | a list of common index files. Specifically: index.html, -- index.xml, index.gif -- -- Typically used as an argument to serveDiretory. defaultIxFiles :: [FilePath] -- | Combine two FilePaths, ensuring that the resulting path leads -- to a file within the first FilePath. -- --
--   >>> combineSafe "/var/uploads/" "etc/passwd"
--   Just "/var/uploads/etc/passwd"
--   
--   >>> combineSafe "/var/uploads/" "/etc/passwd"
--   Nothing
--   
--   >>> combineSafe "/var/uploads/" "../../etc/passwd"
--   Nothing
--   
--   >>> combineSafe "/var/uploads/" "../uploads/home/../etc/passwd"
--   Just "/var/uploads/etc/passwd"
--   
combineSafe :: FilePath -> FilePath -> Maybe FilePath isSafePath :: [FilePath] -> Bool -- | try to find an index file, calls mzero on failure tryIndex :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => (String -> FilePath -> m Response) -> (FilePath -> m String) -> [String] -> FilePath -> m Response -- | attempt to serve index files doIndex :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [FilePath] -> MimeMap -> FilePath -> m Response doIndex' :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => (String -> FilePath -> m Response) -> (FilePath -> m String) -> [String] -> FilePath -> m Response doIndexLazy :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [String] -> MimeMap -> FilePath -> m Response doIndexStrict :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [String] -> MimeMap -> FilePath -> m Response -- | return a simple File not found 404 page. fileNotFound :: (Monad m, FilterMonad Response m) => FilePath -> m Response -- | Returns True if the given String either starts with a . or is of the -- form foo/.bar, e.g. the typical *nix convention for hidden -- files. isDot :: String -> Bool instance [overlap ok] Typeable EntryKind instance [overlap ok] Typeable Browsing instance [overlap ok] Eq EntryKind instance [overlap ok] Ord EntryKind instance [overlap ok] Read EntryKind instance [overlap ok] Show EntryKind instance [overlap ok] Data EntryKind instance [overlap ok] Enum EntryKind instance [overlap ok] Eq Browsing instance [overlap ok] Enum Browsing instance [overlap ok] Ord Browsing instance [overlap ok] Read Browsing instance [overlap ok] Show Browsing instance [overlap ok] Data Browsing -- | functions for serving static files from the disk module Happstack.Server.FileServe -- | see serveDirectory data Browsing EnableBrowsing :: Browsing DisableBrowsing :: Browsing -- | Serve files and directories from a directory and its subdirectories -- using sendFile. -- -- Usage: -- --
--   serveDirectory EnableBrowsing ["index.html"] "path/to/files/on/disk"
--   
-- -- If the requested path does not match a file or directory on the disk, -- then serveDirectory calls mzero. -- -- If the requested path is a file then the file is served normally. -- -- If the requested path is a directory, then the result depends on what -- the first two arguments to the function are. -- -- The first argument controls whether directory browsing is enabled. -- -- The second argument is a list of index files (such as index.html). -- -- When a directory is requested, serveDirectory will first try to -- find one of the index files (in the order they are listed). If that -- fails, it will show a directory listing if EnableBrowsing is -- set, otherwise it will return forbidden "Directory index -- forbidden". -- -- Here is an explicit list of all the possible outcomes when the -- argument is a (valid) directory: -- -- -- -- This will always return, forbidden "Directory index forbidden" -- -- -- --
    --
  1. If an index file is found it will be shown.
  2. --
  3. Otherwise returns, forbidden "Directory index forbidden"
  4. --
-- -- -- -- Always shows a directory index. -- -- -- --
    --
  1. If an index file is found it will be shown
  2. --
  3. Otherwise shows a directory index
  4. --
-- -- see also: defaultIxFiles, serveFile serveDirectory :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => Browsing -> [FilePath] -> FilePath -> m Response -- | Serve a single, specified file. The name of the file being served is -- specified explicity. It is not derived automatically from the -- Request url. -- -- example 1: -- -- Serve as a specific content-type: -- --
--   serveFile (asContentType "image/jpeg") "/srv/data/image.jpg"
--   
-- -- example 2: -- -- Serve guessing the content-type from the extension: -- --
--   serveFile (guessContentTypeM mimeTypes) "/srv/data/image.jpg"
--   
-- -- If the specified path does not exist or is not a file, this function -- will return mzero. -- -- WARNING: No security checks are performed. -- -- NOTE: alias for serveFileUsing filePathSendFile serveFile :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => (FilePath -> m String) -> FilePath -> m Response -- | Like serveFile, but uses combineSafe to prevent -- directory traversal attacks when the path to the file is supplied by -- the user. serveFileFrom :: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => FilePath -> (FilePath -> m String) -> FilePath -> m Response -- | a Map from file extensions to content-types -- -- example: -- --
--   myMimeMap :: MimeMap
--   myMimeMap = Map.fromList [("gz","application/x-gzip"), ... ]
--   
-- -- see also: mimeTypes type MimeMap = Map String String -- | Ready collection of common mime types. Except for the first two -- entries, the mappings come from an Ubuntu 8.04 /etc/mime.types file. mimeTypes :: MimeMap -- | returns a specific content type, completely ignoring the -- FilePath argument. -- -- Use this with serveFile if you want to explicitly specify the -- content-type. -- -- see also: guessContentTypeM, serveFile asContentType :: Monad m => String -> (FilePath -> m String) -- | try to guess the content-type of a file based on its extension -- -- defaults to application/octet-stream if no match was found. -- -- Useful as an argument to serveFile -- -- see also: guessContentType, serveFile guessContentTypeM :: Monad m => MimeMap -> (FilePath -> m String) -- | a list of common index files. Specifically: index.html, -- index.xml, index.gif -- -- Typically used as an argument to serveDiretory. defaultIxFiles :: [FilePath] -- | Serve files from a directory and its subdirectories using -- sendFile. -- -- Usage: -- --
--   fileServe ["index.html"] "path/to/files/on/disk"
--   
-- -- fileServe does not support directory browsing. See -- serveDirectory -- -- DEPRECATED: use serveDirectory instead. -- -- Note: -- -- The list of index files ["index.html"] is only used to -- determine what file to show if the user requests a directory. You *do -- not* need to explicitly list all the files you want to serve. fileServe :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [FilePath] -> FilePath -> m Response -- | Route an incoming Request to a handler. For more in-depth -- documentation see this section of the Happstack Crash Course: -- http://happstack.com/docs/crashcourse/RouteFilters.html module Happstack.Server.Routing -- | guard which checks that an insecure connection was made via http:// -- -- Example: -- --
--   handler :: ServerPart Response
--   handler =
--       do https
--          ...
--   
http :: (ServerMonad m, MonadPlus m) => m () -- | guard which checks that a secure connection was made via https:// -- -- Example: -- --
--   handler :: ServerPart Response
--   handler =
--       do https
--          ...
--   
https :: (ServerMonad m, MonadPlus m) => m () -- | Guard against the method. This function also guards against *any -- remaining path segments*. See method for the version that -- guards only by method. -- -- Example: -- --
--   handler :: ServerPart Response
--   handler =
--       do methodM [GET, HEAD]
--          ...
--   
-- -- NOTE: This function is largely retained for backwards compatibility. -- The fact that implicitly calls nullDir is often forgotten and -- leads to confusion. It is probably better to just use method -- and call nullDir explicitly. -- -- This function will likely be deprecated in the future. methodM :: (ServerMonad m, MonadPlus m, MatchMethod method) => method -> m () -- | Guard against the method only (as opposed to methodM). -- -- Example: -- --
--   handler :: ServerPart Response
--   handler =
--       do methodOnly [GET, HEAD]
--          ...
--   
-- | Deprecated: this function is just an alias for method now methodOnly :: (ServerMonad m, MonadPlus m, MatchMethod method) => method -> m () -- | Guard against the method. Note, this function also guards against any -- remaining path segments. Similar to methodM but with a -- different type signature. -- -- Example: -- --
--   handler :: ServerPart Response
--   handler = methodSP [GET, HEAD] $ subHandler
--   
-- -- NOTE: This style of combinator is going to be deprecated in the -- future. It is better to just use method. -- --
--   handler :: ServerPart Response
--   handler = method [GET, HEAD] >> nullDir >> subHandler
--   
-- | Deprecated: use method instead. methodSP :: (ServerMonad m, MonadPlus m, MatchMethod method) => method -> m b -> m b -- | Guard against the method only (as opposed to methodM). -- -- Example: -- --
--   handler :: ServerPart Response
--   handler =
--       do methodOnly [GET, HEAD]
--          ...
--   
method :: (ServerMonad m, MonadPlus m, MatchMethod method) => method -> m () -- | instances of this class provide a variety of ways to match on the -- Request method. -- -- Examples: -- --
--   method GET                  -- match GET or HEAD
--   method [GET, POST]          -- match GET, HEAD or POST
--   method HEAD                 -- match HEAD /but not/ GET
--   method (== GET)             -- match GET or HEAD
--   method (not . (==) DELETE)  -- match any method except DELETE
--   method ()                   -- match any method
--   
-- -- As you can see, GET implies that HEAD should match as well. This is to -- make it harder to write an application that uses HTTP incorrectly. -- Happstack handles HEAD requests automatically, but we still need to -- make sure our handlers don't mismatch or a HEAD will result in a 404. -- -- If you must, you can still do something like this to match GET without -- HEAD: -- --
--   guardRq ((== GET) . rqMethod)
--   
class MatchMethod m matchMethod :: MatchMethod m => m -> Method -> Bool -- | Pop a path element and run the supplied handler if it matches the -- given string. -- --
--   handler :: ServerPart Response
--   handler = dir "foo" $ dir "bar" $ subHandler
--   
-- -- The path element can not contain '/'. See also dirs. dir :: (ServerMonad m, MonadPlus m) => String -> m a -> m a -- | Guard against a FilePath. Unlike dir the FilePath -- may contain '/'. If the guard succeeds, the matched elements will be -- popped from the directory stack. -- --
--   dirs "foo/bar" $ ...
--   
-- -- See also: dir. dirs :: (ServerMonad m, MonadPlus m) => FilePath -> m a -> m a -- | guard which only succeeds if there are no remaining path segments -- -- Often used if you want to explicitly assign a route for / nullDir :: (ServerMonad m, MonadPlus m) => m () -- | Guard which checks that the Request URI ends in '/'. Useful -- for distinguishing between foo and foo/ trailingSlash :: (ServerMonad m, MonadPlus m) => m () -- | The opposite of trailingSlash. noTrailingSlash :: (ServerMonad m, MonadPlus m) => m () -- | Pop any path element and run the handler. -- -- Succeeds if a path component was popped. Fails is the remaining path -- was empty. anyPath :: (ServerMonad m, MonadPlus m) => m r -> m r -- | Pop a path element and parse it using the fromReqURI in the -- FromReqURI class. path :: (FromReqURI a, MonadPlus m, ServerMonad m) => (a -> m b) -> m b -- | Grab the rest of the URL (dirs + query) and passes it to your handler. uriRest :: ServerMonad m => (String -> m a) -> m a -- | Guard against the host. -- -- This matches against the host header specified in the -- incoming Request. -- -- Can be used to support virtual hosting, -- http://en.wikipedia.org/wiki/Virtual_hosting -- -- see also: withHost host :: (ServerMonad m, MonadPlus m) => String -> m a -> m a -- | Lookup the host header in the incoming request and pass it to -- the handler. -- -- see also: host withHost :: (ServerMonad m, MonadPlus m) => (String -> m a) -> m a -- | Guard using an arbitrary function on the Request. guardRq :: (ServerMonad m, MonadPlus m) => (Request -> Bool) -> m () instance [overlap ok] MatchMethod () instance [overlap ok] MatchMethod (Method -> Bool) instance [overlap ok] MatchMethod [Method] instance [overlap ok] MatchMethod Method -- | simpleHTTP is a self-contained HTTP server which can be used to -- run a ServerPart. -- -- A very simple, "Hello World!" web app looks like: -- --
--   import Happstack.Server
--   main = simpleHTTP nullConf $ ok "Hello World!"
--   
-- -- By default the server will listen on port 8000. Run the app and point -- your browser at: http://localhost:8000/ -- -- For FastCGI support see: -- http://hackage.haskell.org/package/happstack-fastcgi module Happstack.Server.SimpleHTTP -- | start the server, and handle requests using the supplied -- ServerPart. -- -- This function will not return, though it may throw an exception. -- -- NOTE: The server will only listen on IPv4 due to portability issues in -- the Network module. For IPv6 support, use -- simpleHTTPWithSocket with custom socket. simpleHTTP :: ToMessage a => Conf -> ServerPartT IO a -> IO () -- | A combination of simpleHTTP'' and mapServerPartT. See -- mapServerPartT for a discussion of the first argument of this -- function. -- -- NOTE: This function always binds to IPv4 ports until Network module is -- fixed to support IPv6 in a portable way. Use -- simpleHTTPWithSocket with custom socket if you want different -- behaviour. simpleHTTP' :: (ToMessage b, Monad m, Functor m) => (UnWebT m a -> UnWebT IO b) -> Conf -> ServerPartT m a -> IO () -- | Generate a result from a ServerPartT and a Request. This -- is mainly used by CGI (and fast-cgi) wrappers. simpleHTTP'' :: (ToMessage b, Monad m, Functor m) => ServerPartT m b -> Request -> m Response -- | Run simpleHTTP with a previously bound socket. Useful if you -- want to run happstack as user on port 80. Use something like this: -- --
--   import System.Posix.User (setUserID, UserEntry(..), getUserEntryForName)
--   
--   main = do
--       let conf = nullConf { port = 80 }
--       socket <- bindPort conf
--       -- do other stuff as root here
--       getUserEntryForName "www" >>= setUserID . userID
--       -- finally start handling incoming requests
--       tid <- forkIO $ simpleHTTPWithSocket socket Nothing conf impl
--   
-- -- Note: It's important to use the same conf (or at least the same port) -- for bindPort and simpleHTTPWithSocket. -- -- see also: bindPort, bindIPv4 simpleHTTPWithSocket :: ToMessage a => Socket -> Conf -> ServerPartT IO a -> IO () -- | Like simpleHTTP' with a socket. simpleHTTPWithSocket' :: (ToMessage b, Monad m, Functor m) => (UnWebT m a -> UnWebT IO b) -> Socket -> Conf -> ServerPartT m a -> IO () -- | Bind port and return the socket for use with -- simpleHTTPWithSocket. This function always binds to IPv4 ports -- until Network module is fixed to support IPv6 in a portable way. bindPort :: Conf -> IO Socket -- | Bind to ip and port and return the socket for use with -- simpleHTTPWithSocket. -- --
--   import Happstack.Server
--   
--   main = do let conf = nullConf
--                 addr = "127.0.0.1"
--             s <- bindIPv4 addr (port conf)
--             simpleHTTPWithSocket s conf $ ok $ toResponse $ 
--               "now listening on ip addr " ++ addr ++ 
--               " and port " ++ show (port conf)
--   
bindIPv4 :: String -> Int -> IO Socket -- | Parse command line options into a Conf. parseConfig :: [String] -> Either [String] Conf -- | Wait for a signal. On unix, a signal is sigINT or sigTERM (aka -- Control-C). -- -- On windows, the signal is entering: e return waitForTermination :: IO () -- | Filter for compressing the Response body. module Happstack.Server.Internal.Compression -- | reads the Accept-Encoding header. Then, if possible will -- compress the response body with methods gzip or -- deflate. -- --
--   main =
--     simpleHTTP nullConf $
--        do str <- compressedResponseFilter
--           return $ toResponse ("This response compressed using: " ++ str)
--   
compressedResponseFilter :: (FilterMonad Response m, MonadPlus m, WebMonad Response m, ServerMonad m) => m String -- | Ignore the Accept-Encoding header in the Request and -- attempt to compress the body of the response using the supplied -- compressor. -- -- We can not compress files being transfered using SendFile. If -- identity is an allowed encoding, then just return the -- Response unmodified. Otherwise we return 406 Not -- Acceptable. -- -- see also: gzipFilter and defaultFilter compressWithFilter :: FilterMonad Response m => (ByteString -> ByteString) -> String -> Bool -> m () -- | Ignore the Accept-Encoding header in the Request and -- attempt to compress the body of the response with gzip. -- -- calls compressWithFilter using compress. -- -- see also: compressedResponseFilter gzipFilter :: FilterMonad Response m => String -> Bool -> m () -- | Ignore the Accept-Encoding header in the Request and -- attempt compress the body of the response with zlib's deflate -- method -- -- calls compressWithFilter using compress. -- -- see also: compressedResponseFilter deflateFilter :: FilterMonad Response m => String -> Bool -> m () -- | a parser for the Accept-Encoding header encodings :: GenParser Char st [(String, Maybe Double)] module Happstack.Server.I18N -- | parse the 'Accept-Language' header, or [] if not found. acceptLanguage :: Happstack m => m [(Text, Maybe Double)] -- | deconstruct the acceptLanguage results a return a list of -- languages sorted by preference in descending order. -- -- Note: this implementation does not conform to RFC4647 -- -- Among other things, it does not handle wildcards. A proper -- implementation needs to take a list of available languages. bestLanguage :: [(Text, Maybe Double)] -> [Text] -- | Filter for compressing the Response body. module Happstack.Server.Compression -- | reads the Accept-Encoding header. Then, if possible will -- compress the response body with methods gzip or -- deflate. -- --
--   main =
--     simpleHTTP nullConf $
--        do str <- compressedResponseFilter
--           return $ toResponse ("This response compressed using: " ++ str)
--   
compressedResponseFilter :: (FilterMonad Response m, MonadPlus m, WebMonad Response m, ServerMonad m) => m String -- | Happstack.Server provides a self-contained HTTP server and a rich -- collection of types and functions for routing Requests, generating -- Responses, working with query parameters, form data, and cookies, -- serving files and more. -- -- A very simple, "Hello World!" web app looks like: -- --
--   import Happstack.Server
--   main = simpleHTTP nullConf $ ok "Hello World!"
--   
-- -- By default the server will listen on port 8000. Run the app and point -- your browser at: http://localhost:8000/ -- -- At the core of the Happstack server we have the simpleHTTP -- function which starts the HTTP server: -- --
--   simpleHTTP :: ToMessage a => Conf -> ServerPart a -> IO ()
--   
-- -- and we have the user supplied ServerPart (also known as, -- ServerPartT IO), which generates a Response for -- each incoming Request. -- -- A trivial HTTP app server might just take a user supplied function -- like: -- --
--   myApp :: Request -> IO Response
--   
-- -- For each incoming Request the server would fork a new thread, -- run myApp to generate a Response, and then send the -- Response back to the client. But, that would be a pretty barren -- wasteland to work in. -- -- The model for ServerPart is essential the same, except we use -- the much richer ServerPart monad instead of the IO -- monad. -- -- For in-depth documentation and runnable examples I highly recommend -- The Happstack Crash Course -- http://happstack.com/docs/crashcourse/index.html. module Happstack.Server