-- 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.5.3 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 GHC.Show.Show Happstack.Server.Internal.Cookie.CookieLife instance GHC.Read.Read Happstack.Server.Internal.Cookie.CookieLife instance GHC.Classes.Ord Happstack.Server.Internal.Cookie.CookieLife instance GHC.Classes.Eq Happstack.Server.Internal.Cookie.CookieLife instance Data.Data.Data Happstack.Server.Internal.Cookie.Cookie instance GHC.Read.Read Happstack.Server.Internal.Cookie.Cookie instance GHC.Classes.Eq Happstack.Server.Internal.Cookie.Cookie instance GHC.Show.Show Happstack.Server.Internal.Cookie.Cookie module Happstack.Server.Internal.LogFormat -- | Format the time as describe in the Apache combined log format. -- http://httpd.apache.org/docs/2.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.org/docs/2.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 -- | Parsing of RFC822-style headers (name, value pairs) Partly based on -- code from WASHMail. module Happstack.Server.Internal.RFC822Headers type Header = (String, String) pHeader :: Parser Header pHeaders :: Parser [Header] parseHeaders :: Monad m => SourceName -> String -> m [Header] -- | 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)] getContentType :: Monad m => [Header] -> m ContentType -- | Parse the standard representation of a content-type. If the input -- cannot be parsed, this function calls fail with a (hopefully) -- informative error message. parseContentType :: Monad m => String -> m ContentType -- | Produce the standard string representation of a content-type, e.g. -- "text/html; charset=ISO-8859-1". showContentType :: ContentType -> String data ContentTransferEncoding ContentTransferEncoding :: String -> ContentTransferEncoding getContentTransferEncoding :: Monad m => [Header] -> m ContentTransferEncoding parseContentTransferEncoding :: Monad m => String -> m ContentTransferEncoding data ContentDisposition ContentDisposition :: String -> [(String, String)] -> ContentDisposition getContentDisposition :: Monad m => [Header] -> m ContentDisposition parseContentDisposition :: Monad m => String -> m ContentDisposition parseM :: Monad m => Parser a -> SourceName -> String -> m a instance GHC.Classes.Ord Happstack.Server.Internal.RFC822Headers.ContentDisposition instance GHC.Classes.Eq Happstack.Server.Internal.RFC822Headers.ContentDisposition instance GHC.Read.Read Happstack.Server.Internal.RFC822Headers.ContentDisposition instance GHC.Show.Show Happstack.Server.Internal.RFC822Headers.ContentDisposition instance GHC.Classes.Ord Happstack.Server.Internal.RFC822Headers.ContentTransferEncoding instance GHC.Classes.Eq Happstack.Server.Internal.RFC822Headers.ContentTransferEncoding instance GHC.Read.Read Happstack.Server.Internal.RFC822Headers.ContentTransferEncoding instance GHC.Show.Show Happstack.Server.Internal.RFC822Headers.ContentTransferEncoding instance GHC.Classes.Ord Happstack.Server.Internal.RFC822Headers.ContentType instance GHC.Classes.Eq Happstack.Server.Internal.RFC822Headers.ContentType instance GHC.Read.Read Happstack.Server.Internal.RFC822Headers.ContentType instance GHC.Show.Show Happstack.Server.Internal.RFC822Headers.ContentType module Happstack.Server.Internal.Socket -- | alternative implementation of accept to work around EAI_AGAIN errors acceptLite :: Socket -> IO (Socket, HostName, PortNumber) sockAddrToPeer :: SockAddr -> (HostName, PortNumber) 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 () forceTimeout :: Handle -> IO () -- | terminate all threads immediately forceTimeoutAll :: Manager -> 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 (Maybe ByteString) -> IO ByteString -> (FilePath -> Offset -> ByteCount -> IO ()) -> IO () -> Bool -> TimeoutIO [toHandle] :: TimeoutIO -> Handle [toPutLazy] :: TimeoutIO -> ByteString -> IO () [toPut] :: TimeoutIO -> ByteString -> IO () [toGet] :: TimeoutIO -> IO (Maybe ByteString) [toGetContents] :: TimeoutIO -> IO ByteString [toSendFile] :: TimeoutIO -> FilePath -> Offset -> ByteCount -> IO () [toShutdown] :: TimeoutIO -> IO () [toSecure] :: TimeoutIO -> Bool -- |
-- 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 -- | Implementation of askRqEnv for arbitrary ServerMonad. smAskRqEnv :: (ServerMonad m, MonadIO m) => m ([(String, Input)], Maybe [(String, Input)], [(String, Cookie)]) -- | Implementation of localRqEnv for arbitrary -- ServerMonad. smLocalRqEnv :: (ServerMonad m, MonadIO m) => (([(String, Input)], Maybe [(String, Input)], [(String, Cookie)]) -> ([(String, Input)], Maybe [(String, Input)], [(String, Cookie)])) -> m b -> m b -- | 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 -- | Ignores all previous alterations to your filter -- -- As an example: -- --
-- do -- composeFilter f -- setFilter g -- return "Hello World" ---- -- The setFilter g will cause the first -- composeFilter f to be ignored. setFilter :: FilterMonad a m => (a -> a) -> m () -- | Composes your filter function with the existing filter function. composeFilter :: FilterMonad a m => (a -> a) -> m () -- | Retrieves the filter from the environment. 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, MonadPlus 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 failResponse :: String -> Response failHtml :: String -> String escapeString :: String -> String escapeHTTP :: (ServerMonad m, MonadIO m) => (TimeoutIO -> IO ()) -> m a instance GHC.Base.Functor m => GHC.Base.Functor (Happstack.Server.Internal.Monads.ServerPartT m) instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Happstack.Server.Internal.Monads.ServerPartT m) instance GHC.Base.Monad m => GHC.Base.Monad (Happstack.Server.Internal.Monads.ServerPartT m) instance GHC.Base.Functor m => GHC.Base.Functor (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Trans.Class.MonadTrans (Happstack.Server.Internal.Monads.FilterT a) instance GHC.Base.Monad m => GHC.Base.Monad (Happstack.Server.Internal.Monads.FilterT a m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Happstack.Server.Internal.Monads.FilterT a m) instance GHC.Base.Functor m => GHC.Base.Functor (Happstack.Server.Internal.Monads.FilterT a m) instance GHC.Show.Show a => GHC.Show.Show (Happstack.Server.Internal.Monads.SetAppend a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Happstack.Server.Internal.Monads.SetAppend a) instance GHC.Base.Monad m => Happstack.Server.Internal.Monads.WebMonad Happstack.Server.Internal.Types.Response (Happstack.Server.Internal.Monads.ServerPartT m) instance GHC.Base.Monad m => Happstack.Server.Internal.Monads.WebMonad Happstack.Server.Internal.Types.Response (Happstack.Server.Internal.Monads.WebT m) instance Happstack.Server.Internal.Monads.WebMonad a m => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.Reader.ReaderT r m) instance Happstack.Server.Internal.Monads.WebMonad a m => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.State.Lazy.StateT s m) instance Happstack.Server.Internal.Monads.WebMonad a m => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.State.Strict.StateT s m) instance (Happstack.Server.Internal.Monads.WebMonad a m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance (Happstack.Server.Internal.Monads.WebMonad a m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (Happstack.Server.Internal.Monads.WebMonad a m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.RWS.Lazy.RWST r w s m) instance (Happstack.Server.Internal.Monads.WebMonad a m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.RWS.Strict.RWST r w s m) instance (Control.Monad.Trans.Error.Error e, Happstack.Server.Internal.Monads.WebMonad a m) => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.Error.ErrorT e m) instance Happstack.Server.Internal.Monads.WebMonad a m => Happstack.Server.Internal.Monads.WebMonad a (Control.Monad.Trans.Except.ExceptT e m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.Trans.Control.MonadTransControl Happstack.Server.Internal.Monads.ServerPartT instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.Trans.Class.MonadTrans Happstack.Server.Internal.Monads.ServerPartT instance (GHC.Base.Monad m, GHC.Base.MonadPlus m) => GHC.Base.Semigroup (Happstack.Server.Internal.Monads.ServerPartT m a) instance (GHC.Base.Monad m, GHC.Base.MonadPlus m) => GHC.Base.Monoid (Happstack.Server.Internal.Monads.ServerPartT m a) instance (GHC.Base.Monad m, GHC.Base.Functor m) => GHC.Base.Applicative (Happstack.Server.Internal.Monads.ServerPartT m) instance (GHC.Base.Functor m, GHC.Base.MonadPlus m) => GHC.Base.Alternative (Happstack.Server.Internal.Monads.ServerPartT m) instance (GHC.Base.Monad m, Control.Monad.Writer.Class.MonadWriter w m) => Control.Monad.Writer.Class.MonadWriter w (Happstack.Server.Internal.Monads.ServerPartT m) instance (GHC.Base.Monad m, Control.Monad.Error.Class.MonadError e m) => Control.Monad.Error.Class.MonadError e (Happstack.Server.Internal.Monads.ServerPartT m) instance (GHC.Base.Monad m, Control.Monad.Reader.Class.MonadReader r m) => Control.Monad.Reader.Class.MonadReader r (Happstack.Server.Internal.Monads.ServerPartT m) instance (GHC.Base.Monad m, Control.Monad.State.Class.MonadState s m) => Control.Monad.State.Class.MonadState s (Happstack.Server.Internal.Monads.ServerPartT m) instance GHC.Base.Monad m => Happstack.Server.Internal.Monads.FilterMonad Happstack.Server.Internal.Types.Response (Happstack.Server.Internal.Monads.ServerPartT m) instance GHC.Base.Monad m => Happstack.Server.Internal.Monads.ServerMonad (Happstack.Server.Internal.Monads.ServerPartT m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Trans.Control.MonadTransControl Happstack.Server.Internal.Monads.WebT instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Happstack.Server.Internal.Monads.WebT m) instance GHC.Base.Monad m => GHC.Base.Monad (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Trans.Class.MonadTrans Happstack.Server.Internal.Monads.WebT instance (GHC.Base.Monad m, GHC.Base.MonadPlus m) => GHC.Base.MonadPlus (Happstack.Server.Internal.Monads.WebT m) instance GHC.Base.Monad m => Happstack.Server.Internal.Monads.FilterMonad Happstack.Server.Internal.Types.Response (Happstack.Server.Internal.Monads.WebT m) instance (GHC.Base.Monad m, GHC.Base.MonadPlus m) => GHC.Base.Semigroup (Happstack.Server.Internal.Monads.WebT m a) instance (GHC.Base.Monad m, GHC.Base.MonadPlus m) => GHC.Base.Monoid (Happstack.Server.Internal.Monads.WebT m a) instance (GHC.Base.Monad m, GHC.Base.Functor m) => GHC.Base.Applicative (Happstack.Server.Internal.Monads.WebT m) instance (GHC.Base.Functor m, GHC.Base.MonadPlus m) => GHC.Base.Alternative (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.State.Class.MonadState st m => Control.Monad.State.Class.MonadState st (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Happstack.Server.Internal.Monads.WebT m) instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Happstack.Server.Internal.Monads.WebT m) instance GHC.Base.Monad m => Happstack.Server.Internal.Monads.FilterMonad a (Happstack.Server.Internal.Monads.FilterT a m) instance Happstack.Server.Internal.Monads.FilterMonad res m => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.Reader.ReaderT r m) instance Happstack.Server.Internal.Monads.FilterMonad res m => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.State.Lazy.StateT s m) instance Happstack.Server.Internal.Monads.FilterMonad res m => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.State.Strict.StateT s m) instance (Happstack.Server.Internal.Monads.FilterMonad res m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance (Happstack.Server.Internal.Monads.FilterMonad res m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (Happstack.Server.Internal.Monads.FilterMonad res m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.RWS.Lazy.RWST r w s m) instance (Happstack.Server.Internal.Monads.FilterMonad res m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.FilterMonad res (Control.Monad.Trans.RWS.Strict.RWST r w s m) instance (Control.Monad.Trans.Error.Error e, Happstack.Server.Internal.Monads.FilterMonad a m) => Happstack.Server.Internal.Monads.FilterMonad a (Control.Monad.Trans.Error.ErrorT e m) instance Happstack.Server.Internal.Monads.FilterMonad a m => Happstack.Server.Internal.Monads.FilterMonad a (Control.Monad.Trans.Except.ExceptT e m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Happstack.Server.Internal.Monads.FilterT a m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Happstack.Server.Internal.Monads.FilterT a m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Happstack.Server.Internal.Monads.FilterT a m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Happstack.Server.Internal.Monads.FilterT a m) instance Control.Monad.Trans.Control.MonadTransControl (Happstack.Server.Internal.Monads.FilterT a) instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Happstack.Server.Internal.Monads.FilterT a m) instance GHC.Base.Monoid a => GHC.Base.Semigroup (Happstack.Server.Internal.Monads.SetAppend a) instance GHC.Base.Monoid a => GHC.Base.Monoid (Happstack.Server.Internal.Monads.SetAppend a) instance GHC.Base.Functor Happstack.Server.Internal.Monads.SetAppend instance Happstack.Server.Internal.Monads.ServerMonad m => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Reader.ReaderT r m) instance Happstack.Server.Internal.Monads.ServerMonad m => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.State.Lazy.StateT s m) instance Happstack.Server.Internal.Monads.ServerMonad m => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.State.Strict.StateT s m) instance (Happstack.Server.Internal.Monads.ServerMonad m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance (Happstack.Server.Internal.Monads.ServerMonad m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (Happstack.Server.Internal.Monads.ServerMonad m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.RWS.Lazy.RWST r w s m) instance (Happstack.Server.Internal.Monads.ServerMonad m, GHC.Base.Monoid w) => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.RWS.Strict.RWST r w s m) instance (Control.Monad.Trans.Error.Error e, Happstack.Server.Internal.Monads.ServerMonad m) => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Error.ErrorT e m) instance Happstack.Server.Internal.Monads.ServerMonad m => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Except.ExceptT e m) -- | Functions and classes related to generating a Response and -- setting the response code. For detailed instruction see the Happstack -- Crash Course: -- http://www.happstack.com/docs/crashcourse/index.html#creating-a-response 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 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 Happstack.Server.Response.ToMessage () instance Happstack.Server.Response.ToMessage GHC.Base.String instance Happstack.Server.Response.ToMessage Data.Text.Internal.Text instance Happstack.Server.Response.ToMessage Data.Text.Internal.Lazy.Text instance Happstack.Server.Response.ToMessage GHC.Integer.Type.Integer instance Happstack.Server.Response.ToMessage a => Happstack.Server.Response.ToMessage (GHC.Maybe.Maybe a) instance Happstack.Server.Response.ToMessage Text.Html.Html instance Happstack.Server.Response.ToMessage Text.XHtml.Internals.Html instance Happstack.Server.Response.ToMessage Text.Blaze.Html.Html instance Happstack.Server.Response.ToMessage Happstack.Server.Internal.Types.Response instance Happstack.Server.Response.ToMessage Data.ByteString.Lazy.Internal.ByteString instance Happstack.Server.Response.ToMessage Data.ByteString.Internal.ByteString -- | 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 -- | 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 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://www.happstack.com/docs/crashcourse/index.html#parsing-request-data-from-the-query_string-cookies-and-request-body 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: -- --
-- 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: -- --
-- 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 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 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, PUT, PATCH, etc.
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, PUT, PATCH, etc.
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, PUT, PATCH, etc.
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, PUT, PATCH, etc.
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
-- | lift some Errors into RqData
rqDataError :: HasRqData m => Errors String -> m a
instance Control.Monad.Reader.Class.MonadReader Happstack.Server.RqData.RqEnv Happstack.Server.RqData.RqData
instance GHC.Base.Alternative Happstack.Server.RqData.RqData
instance GHC.Base.Applicative Happstack.Server.RqData.RqData
instance GHC.Base.MonadPlus Happstack.Server.RqData.RqData
instance GHC.Base.Monad Happstack.Server.RqData.RqData
instance GHC.Base.Functor Happstack.Server.RqData.RqData
instance Data.Data.Data a => Data.Data.Data (Happstack.Server.RqData.Errors a)
instance GHC.Read.Read a => GHC.Read.Read (Happstack.Server.RqData.Errors a)
instance GHC.Show.Show a => GHC.Show.Show (Happstack.Server.RqData.Errors a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Happstack.Server.RqData.Errors a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Happstack.Server.RqData.Errors a)
instance (Control.Monad.Trans.Error.Error e, GHC.Base.Monoid e) => GHC.Base.MonadPlus (Happstack.Server.RqData.ReaderError r e)
instance (GHC.Base.Monoid e, Control.Monad.Trans.Error.Error e) => GHC.Base.Monad (Happstack.Server.RqData.ReaderError r e)
instance GHC.Base.Functor (Happstack.Server.RqData.ReaderError r e)
instance (Happstack.Server.RqData.FromData a, Happstack.Server.RqData.FromData b) => Happstack.Server.RqData.FromData (a, b)
instance (Happstack.Server.RqData.FromData a, Happstack.Server.RqData.FromData b, Happstack.Server.RqData.FromData c) => Happstack.Server.RqData.FromData (a, b, c)
instance (Happstack.Server.RqData.FromData a, Happstack.Server.RqData.FromData b, Happstack.Server.RqData.FromData c, Happstack.Server.RqData.FromData d) => Happstack.Server.RqData.FromData (a, b, c, d)
instance Happstack.Server.RqData.FromData a => Happstack.Server.RqData.FromData (GHC.Maybe.Maybe a)
instance Happstack.Server.RqData.HasRqData Happstack.Server.RqData.RqData
instance (Control.Monad.IO.Class.MonadIO m, GHC.Base.MonadPlus m) => Happstack.Server.RqData.HasRqData (Happstack.Server.Internal.Monads.ServerPartT m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.Reader.ReaderT s m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.State.Lazy.StateT s m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.State.Strict.StateT s m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m, GHC.Base.Monoid w) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m, GHC.Base.Monoid w) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m, GHC.Base.Monoid w) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m, GHC.Base.Monoid w) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.RWS.Strict.RWST r w s m)
instance (GHC.Base.Monad m, Control.Monad.Trans.Error.Error e, Happstack.Server.RqData.HasRqData m) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.Error.ErrorT e m)
instance (GHC.Base.Monad m, Happstack.Server.RqData.HasRqData m) => Happstack.Server.RqData.HasRqData (Control.Monad.Trans.Except.ExceptT e m)
instance GHC.Base.Semigroup (Happstack.Server.RqData.Errors a)
instance GHC.Base.Monoid (Happstack.Server.RqData.Errors a)
instance Control.Monad.Trans.Error.Error (Happstack.Server.RqData.Errors GHC.Base.String)
instance (Control.Monad.Trans.Error.Error e, GHC.Base.Monoid e) => Control.Monad.Reader.Class.MonadReader r (Happstack.Server.RqData.ReaderError r e)
instance (GHC.Base.Monoid e, Control.Monad.Trans.Error.Error e) => GHC.Base.Applicative (Happstack.Server.RqData.ReaderError r e)
instance (GHC.Base.Monoid e, Control.Monad.Trans.Error.Error e) => GHC.Base.Alternative (Happstack.Server.RqData.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 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 -- | Ignores all previous alterations to your filter -- -- As an example: -- --
-- do -- composeFilter f -- setFilter g -- return "Hello World" ---- -- The setFilter g will cause the first -- composeFilter f to be ignored. setFilter :: FilterMonad a m => (a -> a) -> m () -- | Composes your filter function with the existing filter function. composeFilter :: FilterMonad a m => (a -> a) -> m () -- | Retrieves the filter from the environment. 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 escapeHTTP :: (ServerMonad m, MonadIO m) => (TimeoutIO -> IO ()) -> m a instance (GHC.Base.Functor m, GHC.Base.Monad m, GHC.Base.MonadPlus m, Control.Monad.IO.Class.MonadIO m) => Happstack.Server.Monads.Happstack (Happstack.Server.Internal.Monads.ServerPartT m) instance Happstack.Server.Monads.Happstack m => Happstack.Server.Monads.Happstack (Control.Monad.Trans.State.Lazy.StateT s m) instance Happstack.Server.Monads.Happstack m => Happstack.Server.Monads.Happstack (Control.Monad.Trans.State.Strict.StateT s m) instance Happstack.Server.Monads.Happstack m => Happstack.Server.Monads.Happstack (Control.Monad.Trans.Reader.ReaderT r m) instance (Happstack.Server.Monads.Happstack m, GHC.Base.Monoid w) => Happstack.Server.Monads.Happstack (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance (Happstack.Server.Monads.Happstack m, GHC.Base.Monoid w) => Happstack.Server.Monads.Happstack (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (Happstack.Server.Monads.Happstack m, GHC.Base.Monoid w) => Happstack.Server.Monads.Happstack (Control.Monad.Trans.RWS.Lazy.RWST r w s m) instance (Happstack.Server.Monads.Happstack m, GHC.Base.Monoid w) => Happstack.Server.Monads.Happstack (Control.Monad.Trans.RWS.Strict.RWST r w s m) instance (Happstack.Server.Monads.Happstack m, Control.Monad.Trans.Error.Error e) => Happstack.Server.Monads.Happstack (Control.Monad.Trans.Error.ErrorT e m) instance (Happstack.Server.Monads.Happstack m, GHC.Base.Monoid e) => Happstack.Server.Monads.Happstack (Control.Monad.Trans.Except.ExceptT e m) -- | Route an incoming Request to a handler. For more in-depth -- documentation see this section of the Happstack Crash Course: -- http://www.happstack.com/docs/crashcourse/index.html#route-filters module Happstack.Server.Routing -- | guard which checks that an insecure connection was made via http:// -- -- Example: -- --
-- handler :: ServerPart Response -- handler = -- do http -- ... --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 -- -- Note that this matches against the value of the Host header -- which may include the port number. -- -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23 -- -- 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 Happstack.Server.Routing.MatchMethod Happstack.Server.Internal.Types.Method instance Happstack.Server.Routing.MatchMethod [Happstack.Server.Internal.Types.Method] instance Happstack.Server.Routing.MatchMethod (Happstack.Server.Internal.Types.Method -> GHC.Types.Bool) instance Happstack.Server.Routing.MatchMethod () -- | 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: -- --
-- 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 -- | 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 Data.Data.Data Happstack.Server.FileServe.BuildingBlocks.Browsing instance GHC.Show.Show Happstack.Server.FileServe.BuildingBlocks.Browsing instance GHC.Read.Read Happstack.Server.FileServe.BuildingBlocks.Browsing instance GHC.Classes.Ord Happstack.Server.FileServe.BuildingBlocks.Browsing instance GHC.Enum.Enum Happstack.Server.FileServe.BuildingBlocks.Browsing instance GHC.Classes.Eq Happstack.Server.FileServe.BuildingBlocks.Browsing instance GHC.Enum.Enum Happstack.Server.FileServe.BuildingBlocks.EntryKind instance Data.Data.Data Happstack.Server.FileServe.BuildingBlocks.EntryKind instance GHC.Show.Show Happstack.Server.FileServe.BuildingBlocks.EntryKind instance GHC.Read.Read Happstack.Server.FileServe.BuildingBlocks.EntryKind instance GHC.Classes.Ord Happstack.Server.FileServe.BuildingBlocks.EntryKind instance GHC.Classes.Eq Happstack.Server.FileServe.BuildingBlocks.EntryKind -- | 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 -- | 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. -- | Deprecated: use serveDirectory instead. fileServe :: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) => [FilePath] -> FilePath -> m Response -- | 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 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
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)
-- | 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.
--
-- -- 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. -- -- This function uses standardEncodingHandlers. If you want to -- provide alternative handers (perhaps to change compression levels), -- see compressedResponseFilter' -- --
-- 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
-- | reads the Accept-Encoding header. Then, if possible will
-- compress the response body using one of the supplied filters.
--
-- A filter function takes two arguments. The first is a String
-- with the value to be used as the 'Content-Encoding' header. The second
-- is Bool which indicates if the compression filter is allowed to
-- fallback to identity.
--
-- This is important if the resource being sent using sendfile, since
-- sendfile does not provide a compression option. If identity
-- is allowed, then the file can be sent uncompressed using sendfile. But
-- if identity is not allowed, then the filter will need to
-- return error 406.
--
-- You should probably always include the identity and
-- * encodings as acceptable.
--
--
-- myFilters :: (FilterMonad Response m) => [(String, String -> Bool -> m ()]
-- myFilters = [ ("gzip" , gzipFilter)
-- , ("identity", identityFilter)
-- , ("*" , starFilter)
-- ]
--
-- main =
-- simpleHTTP nullConf $
-- do let filters =
-- str <- compressedResponseFilter'
-- return $ toResponse ("This response compressed using: " ++ str)
--
compressedResponseFilter' :: (FilterMonad Response m, MonadPlus m, WebMonad Response m, ServerMonad m) => [(String, String -> Bool -> 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, deflateFilter,
-- identityFilter, starFilter,
-- compressedResponseFilter'
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 ()
-- | compression filter for the identity encoding (aka, do nothing)
--
-- see also: compressedResponseFilter
identityFilter :: FilterMonad Response m => String -> Bool -> m ()
-- | compression filter for the * encoding
--
-- This filter always fails.
starFilter :: FilterMonad Response m => String -> Bool -> m ()
-- | a parser for the Accept-Encoding header
encodings :: GenParser Char st [(String, Maybe Double)]
-- | an assoc list of encodings and their corresponding compression
-- functions.
--
-- e.g.
--
--
-- [("gzip", gzipFilter), ("identity", identityFilter), ("*",starFilter)]
--
standardEncodingHandlers :: FilterMonad Response m => [(String, String -> Bool -> m ())]
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.
--
-- This function uses standardEncodingHandlers. If you want to
-- provide alternative handers (perhaps to change compression levels),
-- see compressedResponseFilter'
--
--
-- 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
-- | reads the Accept-Encoding header. Then, if possible will
-- compress the response body using one of the supplied filters.
--
-- A filter function takes two arguments. The first is a String
-- with the value to be used as the 'Content-Encoding' header. The second
-- is Bool which indicates if the compression filter is allowed to
-- fallback to identity.
--
-- This is important if the resource being sent using sendfile, since
-- sendfile does not provide a compression option. If identity
-- is allowed, then the file can be sent uncompressed using sendfile. But
-- if identity is not allowed, then the filter will need to
-- return error 406.
--
-- You should probably always include the identity and
-- * encodings as acceptable.
--
--
-- myFilters :: (FilterMonad Response m) => [(String, String -> Bool -> m ()]
-- myFilters = [ ("gzip" , gzipFilter)
-- , ("identity", identityFilter)
-- , ("*" , starFilter)
-- ]
--
-- main =
-- simpleHTTP nullConf $
-- do let filters =
-- str <- compressedResponseFilter'
-- return $ toResponse ("This response compressed using: " ++ str)
--
compressedResponseFilter' :: (FilterMonad Response m, MonadPlus m, WebMonad Response m, ServerMonad m) => [(String, String -> Bool -> 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, deflateFilter,
-- identityFilter, starFilter,
-- compressedResponseFilter'
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 ()
-- | compression filter for the identity encoding (aka, do nothing)
--
-- see also: compressedResponseFilter
identityFilter :: FilterMonad Response m => String -> Bool -> m ()
-- | compression filter for the * encoding
--
-- This filter always fails.
starFilter :: FilterMonad Response m => String -> Bool -> m ()
-- | an assoc list of encodings and their corresponding compression
-- functions.
--
-- e.g.
--
--
-- [("gzip", gzipFilter), ("identity", identityFilter), ("*",starFilter)]
--
standardEncodingHandlers :: FilterMonad Response m => [(String, String -> Bool -> m ())]
-- | 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 -- | Parse command line options into a Conf. parseConfig :: [String] -> Either [String] Conf -- | 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 -- | 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 ()