-- 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 6.2.2 module Happstack.Server.Internal.TimeoutManager data Manager data Handle initialize :: Int -> IO Manager register :: Manager -> IO () -> IO Handle tickle, cancel, resume, pause :: Handle -> IO () -- | 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, 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 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 -- |
-- 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 Happstack.Server.Error.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. 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. 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] Monad m => Monad (FilterT a m) instance [overlap ok] MonadTrans (FilterT a) instance [overlap ok] Functor m => Functor (FilterT a m) 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] 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] MonadIO m => MonadIO (WebT m) instance [overlap ok] Monad m => FilterMonad a (FilterT a m) instance [overlap ok] MonadIO m => MonadIO (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] MonadIO m => MonadIO (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 :: Seconds -> 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. -- -- 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!" ---- -- Minimal definition: toMessage (and usually -- toContentType). class ToMessage a 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: C.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 -- | 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 :: CalendarTime -> Request -> Response -> Response 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 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 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, Read 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, Read 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: -- --
-- 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 -- | 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: -- --
-- look "key" `checkRq` (readRq "key") ---- -- use with checkRq readRq :: 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, MonadIO 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, MonadIO 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, MonadIO 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, MonadIO 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] 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.
--
-- -- 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 Happstack.Server.Error.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 () -- | 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] (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 :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadPlus 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. 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. -- --
-- 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. 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: -- --
-- 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: -- --
-- 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 -- | 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 (CalendarTime, Request) -> Integer -> Integer -> Response -- | Send the contents of a Lazy ByteString lazyByteStringResponse :: String -> ByteString -> Maybe (CalendarTime, Request) -> Integer -> Integer -> Response -- | Send the contents of a Lazy ByteString strictByteStringResponse :: String -> ByteString -> Maybe (CalendarTime, 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 CalendarTime, 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]
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: -- --
-- 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 -- | 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 against the method. This function also guards against *any -- remaining path segments*. See methodOnly for the version that -- guards only by method. -- -- Example: -- --
-- handler :: ServerPart Response -- handler = -- do methodM [GET, HEAD] -- ... --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] -- ... --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 --methodSP :: (ServerMonad m, MonadPlus m, MatchMethod method) => method -> m b -> m b -- | Guard against the method. Note, this function also guards against any -- remaining path segments. -- -- DEPRECATED: Use methodSP, methodM, or methodOnly method :: (MatchMethod method, Monad m) => method -> WebT m a -> ServerPartT m a -- | instances of this class provide a variety of ways to match on the -- Request method. -- -- Examples -- --
-- methodM GET -- match GET -- methodM [HEAD, GET] -- match HEAD or GET -- methodM (not . (==) DELETE) -- match any method except DELETE -- methodM () -- match any method --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 () -- | 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 -- | 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 -- | 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] FromReqURI Double instance [overlap ok] FromReqURI Float instance [overlap ok] FromReqURI Integer instance [overlap ok] FromReqURI Int instance [overlap ok] FromReqURI String 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 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
bindIPv4 :: String -> Int -> IO Socket
-- | Parse command line options into a Conf.
parseConfig :: [String] -> Either [String] Conf
-- | 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 [([Char], Maybe Double)]
-- | 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
-- | Functions to allow you to use XSLT to transform your output. To use
-- this, you would generally design your happstack application to output
-- XML. The xslt filter will then run an external tool which performs the
-- tranforms. The transformed result will then be sent to the http client
-- as the Response.
--
-- NOTE: This module is currently looking for a maintainer. If you want
-- to improve XSLT support in Happstack, please volunteer!
module Happstack.Server.XSLT
-- | Note that the xsl file must have .xsl suffix.
xsltFile :: XSLPath -> FilePath -> FilePath -> IO ()
-- | Uses the provided xsl file to transform the given string. This
-- function creates temporary files during its execution, but guarantees
-- their cleanup.
xsltString :: XSLPath -> String -> String
-- | Performs an XSL transformation with lists of ByteStrings instead of a
-- String.
xsltFPS :: XSLPath -> [ByteString] -> [ByteString]
-- | Equivalent to xsltFPS but does not hide the inherent IO of the
-- low-level ByteString operations.
xsltFPSIO :: XSLPath -> [ByteString] -> IO [ByteString]
type XSLPath = FilePath
-- | Use cmd to transform XML against xslPath. This
-- function only acts if the content-type is application/xml.
xslt :: (MonadIO m, MonadPlus m, ToMessage r) => XSLTCmd -> XSLPath -> m r -> m Response
doXslt :: MonadIO m => XSLTCmd -> XSLPath -> Response -> m Response
-- | Use xsltproc to transform XML.
xsltproc :: XSLTCmd
-- | Use saxon to transform XML.
saxon :: XSLTCmd
procFPSIO :: XSLTCommand -> XSLPath -> [ByteString] -> IO [ByteString]
procLBSIO :: XSLTCmd -> XSLPath -> ByteString -> IO ByteString
type XSLTCommand = XSLPath -> FilePath -> FilePath -> (FilePath, [String])
data XSLTCmd
instance [overlap ok] Data XSLTCmd
instance [overlap ok] Show XSLTCmd
instance [overlap ok] Read XSLTCmd
instance [overlap ok] Eq XSLTCmd
instance [overlap ok] Ord XSLTCmd
instance [overlap ok] Sat (ctx XSLTCmd) => Data ctx XSLTCmd
instance [overlap ok] Typeable XSLTCmd
instance [overlap ok] Default XSLTCmd
-- | 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