-- 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.0 -- | A wrapper and type class so that functions like seeOther can -- take a URI which is represented by a String, URI, or -- other instance of ToSURI. module Happstack.Server.SURI -- | Retrieves the path component from the URI path :: SURI -> String -- | Retrieves the query component from the URI query :: SURI -> String -- | Retrieves the scheme component from the URI scheme :: SURI -> String -- | Modifies the scheme component of the URI using the provided function u_scheme :: (String -> String) -> SURI -> SURI -- | Modifies the path component of the URI using the provided function u_path :: (String -> String) -> SURI -> SURI -- | Sets the scheme component of the URI a_scheme :: String -> SURI -> SURI -- | Sets the path component of the URI a_path :: String -> SURI -> SURI -- | percent decode a String -- -- e.g. "hello%2Fworld" -> "hello/world" percentDecode :: String -> String unEscape :: String -> String unEscapeQS :: String -> String -- | Returns true if the URI is absolute isAbs :: SURI -> Bool newtype SURI SURI :: URI -> SURI [suri] :: SURI -> URI -- | Render should be used for prettyprinting URIs. render :: (ToSURI a) => a -> String -- | Parses a URI from a String. Returns Nothing on failure. parse :: String -> Maybe SURI -- | Convenience class for converting data types to URIs class ToSURI x toSURI :: ToSURI x => x -> SURI class FromPath x fromPath :: FromPath x => String -> x instance Data.Data.Data Happstack.Server.SURI.SURI instance GHC.Classes.Eq Happstack.Server.SURI.SURI instance GHC.Show.Show Happstack.Server.SURI.SURI instance GHC.Read.Read Happstack.Server.SURI.SURI instance GHC.Classes.Ord Happstack.Server.SURI.SURI instance Happstack.Server.SURI.ToSURI Happstack.Server.SURI.SURI instance Happstack.Server.SURI.ToSURI Network.URI.URI instance Happstack.Server.SURI.ToSURI GHC.Base.String instance Happstack.Server.SURI.ToSURI Data.Text.Internal.Text instance Happstack.Server.SURI.ToSURI Data.Text.Internal.Lazy.Text 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 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 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.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.WebMonad 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 GHC.Base.Monoid a => GHC.Base.Monoid (Happstack.Server.Internal.Monads.SetAppend a) instance GHC.Base.Functor Happstack.Server.Internal.Monads.SetAppend 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.Monad m => Happstack.Server.Internal.Monads.FilterMonad a (Happstack.Server.Internal.Monads.FilterT a 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 GHC.Base.Monad m => Happstack.Server.Internal.Monads.WebMonad Happstack.Server.Internal.Types.Response (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.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 Happstack.Server.Internal.Monads.ServerMonad m => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Reader.ReaderT r 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.WebMonad a m => Happstack.Server.Internal.Monads.WebMonad a (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.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.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.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.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.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.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 (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 (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.ServerMonad m) => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Error.ErrorT e 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 (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.ServerMonad m => Happstack.Server.Internal.Monads.ServerMonad (Control.Monad.Trans.Except.ExceptT e m) instance Happstack.Server.Internal.Monads.FilterMonad a m => Happstack.Server.Internal.Monads.FilterMonad a (Control.Monad.Trans.Except.ExceptT e m) instance Happstack.Server.Internal.Monads.WebMonad a m => Happstack.Server.Internal.Monads.WebMonad a (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 where toContentType _ = pack "text/plain" toMessage = error "Happstack.Server.SimpleHTTP.ToMessage.toMessage: Not defined" toResponse val = let bs = toMessage val res = Response 200 empty nullRsFlags bs Nothing in setHeaderBS (pack "Content-Type") (toContentType val) res toContentType :: ToMessage a => a -> ByteString toMessage :: ToMessage a => a -> ByteString toResponse :: ToMessage a => a -> Response -- | alias for: fmap toResponse -- -- turns m a into m Response using -- toResponse. -- --
-- main = simpleHTTP nullConf $ flatten $ do return "flatten me." --flatten :: (ToMessage a, Functor f) => f a -> f Response -- | A low-level function to build a Response from a content-type -- and a ByteString. -- -- Creates a Response in a manner similar to the ToMessage -- class, but without requiring an instance declaration. -- -- example: -- --
-- import Data.ByteString.Char8 as C -- import Data.ByteString.Lazy.Char8 as L -- import Happstack.Server -- -- main = simpleHTTP nullConf $ ok $ toResponseBS (C.pack "text/plain") (L.pack "hello, world") ---- -- (note: pack and pack only work for ascii. For unicode -- strings you would need to use utf8-string, text, or -- something similar to create a valid ByteString). toResponseBS :: ByteString -> ByteString -> Response -- | Respond with 200 OK. -- --
-- main = simpleHTTP nullConf $ ok "Everything is OK" --ok :: (FilterMonad Response m) => a -> m a -- | Respond with 204 No Content -- -- A 204 No Content response may not contain a message-body. If -- you try to supply one, it will be dutifully ignored. -- --
-- main = simpleHTTP nullConf $ noContent "This will be ignored." --noContent :: (FilterMonad Response m) => a -> m a -- | Respond with 500 Internal Server Error. -- --
-- main = simpleHTTP nullConf $ internalServerError "Sorry, there was an internal server error." --internalServerError :: (FilterMonad Response m) => a -> m a -- | Responds with 502 Bad Gateway. -- --
-- main = simpleHTTP nullConf $ badGateway "Bad Gateway." --badGateway :: (FilterMonad Response m) => a -> m a -- | Respond with 400 Bad Request. -- --
-- main = simpleHTTP nullConf $ badRequest "Bad Request." --badRequest :: (FilterMonad Response m) => a -> m a -- | Respond with 401 Unauthorized. -- --
-- main = simpleHTTP nullConf $ unauthorized "You are not authorized." --unauthorized :: (FilterMonad Response m) => a -> m a -- | Respond with 403 Forbidden. -- --
-- main = simpleHTTP nullConf $ forbidden "Sorry, it is forbidden." --forbidden :: (FilterMonad Response m) => a -> m a -- | Respond with 404 Not Found. -- --
-- main = simpleHTTP nullConf $ notFound "What you are looking for has not been found." --notFound :: (FilterMonad Response m) => a -> m a -- | A nicely formatted rendering of a Response prettyResponse :: Response -> String -- | Respond with 413 Request Entity Too Large. -- --
-- main = simpleHTTP nullConf $ requestEntityTooLarge "That's too big for me to handle." --requestEntityTooLarge :: (FilterMonad Response m) => a -> m a -- | Respond with 303 See Other. -- --
-- main = simpleHTTP nullConf $ seeOther "http://example.org/" "What you are looking for is now at http://example.org/" ---- -- NOTE: The second argument of seeOther is the message body which -- will sent to the browser. According to the HTTP 1.1 spec, -- --
-- the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). ---- -- This is because pre-HTTP/1.1 user agents do not support 303. However, -- in practice you can probably just use "" as the second -- argument. seeOther :: (FilterMonad Response m, ToSURI uri) => uri -> res -> m res -- | Respond with 302 Found. -- -- You probably want seeOther. This method is not in popular use -- anymore, and is generally treated like 303 by most user-agents anyway. found :: (FilterMonad Response m, ToSURI uri) => uri -> res -> m res -- | Respond with 301 Moved Permanently. -- --
-- main = simpleHTTP nullConf $ movedPermanently "http://example.org/" "What you are looking for is now at http://example.org/" --movedPermanently :: (FilterMonad Response m, ToSURI a) => a -> res -> m res -- | Respond with 307 Temporary Redirect. -- --
-- main = simpleHTTP nullConf $ tempRedirect "http://example.org/" "What you are looking for is temporarily at http://example.org/" --tempRedirect :: (FilterMonad Response m, ToSURI a) => a -> res -> m res -- | Set an arbitrary return code in your response. -- -- A filter for setting the response code. Generally you will use a -- helper function like ok or seeOther. -- --
-- main = simpleHTTP nullConf $ do setResponseCode 200 -- return "Everything is OK" ---- -- see also: resp setResponseCode :: FilterMonad Response m => Int -> m () -- | Same as setResponseCode status >> return val. -- -- Use this if you want to set a response code that does not already have -- a helper function. -- --
-- main = simpleHTTP nullConf $ resp 200 "Everything is OK" --resp :: (FilterMonad Response m) => Int -> b -> m b -- | Honor an if-modified-since header in a Request. If the -- Request includes the if-modified-since header and the -- Response has not been modified, then return 304 (Not Modified), -- otherwise return the Response. ifModifiedSince :: UTCTime -> Request -> Response -> Response instance 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.Base.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 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 -- | 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 (GHC.Base.Monoid e, Control.Monad.Trans.Error.Error e) => GHC.Base.MonadPlus (Happstack.Server.RqData.ReaderError r e)
instance (Control.Monad.Trans.Error.Error e, GHC.Base.Monoid e) => GHC.Base.Monad (Happstack.Server.RqData.ReaderError r e)
instance GHC.Base.Functor (Happstack.Server.RqData.ReaderError r e)
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)
instance GHC.Base.Monoid (Happstack.Server.RqData.Errors a)
instance Control.Monad.Trans.Error.Error (Happstack.Server.RqData.Errors GHC.Base.String)
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 (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.Base.Maybe a)
-- | 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) -- | 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 -- | 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 -- | 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 () -- | 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. -- --
-- 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
-- | simpleHTTP is a self-contained HTTP server which can be used to
-- run a ServerPart.
--
-- A very simple, "Hello World!" web app looks like:
--
-- -- import Happstack.Server -- main = simpleHTTP nullConf $ ok "Hello World!" ---- -- By default the server will listen on port 8000. Run the app and point -- your browser at: http://localhost:8000/ -- -- For FastCGI support see: -- http://hackage.haskell.org/package/happstack-fastcgi module Happstack.Server.SimpleHTTP -- | start the server, and handle requests using the supplied -- ServerPart. -- -- This function will not return, though it may throw an exception. -- -- NOTE: The server will only listen on IPv4 due to portability issues in -- the Network module. For IPv6 support, use -- simpleHTTPWithSocket with custom socket. simpleHTTP :: (ToMessage a) => Conf -> ServerPartT IO a -> IO () -- | A combination of simpleHTTP'' and mapServerPartT. See -- mapServerPartT for a discussion of the first argument of this -- function. -- -- NOTE: This function always binds to IPv4 ports until Network module is -- fixed to support IPv6 in a portable way. Use -- simpleHTTPWithSocket with custom socket if you want different -- behaviour. simpleHTTP' :: (ToMessage b, Monad m, Functor m) => (UnWebT m a -> UnWebT IO b) -> Conf -> ServerPartT m a -> IO () -- | Generate a result from a ServerPartT and a Request. This -- is mainly used by CGI (and fast-cgi) wrappers. simpleHTTP'' :: (ToMessage b, Monad m, Functor m) => ServerPartT m b -> Request -> m Response -- | Run simpleHTTP with a previously bound socket. Useful if you -- want to run happstack as user on port 80. Use something like this: -- --
-- import System.Posix.User (setUserID, UserEntry(..), getUserEntryForName)
--
-- main = do
-- let conf = nullConf { port = 80 }
-- socket <- bindPort conf
-- -- do other stuff as root here
-- getUserEntryForName "www" >>= setUserID . userID
-- -- finally start handling incoming requests
-- tid <- forkIO $ simpleHTTPWithSocket socket Nothing conf impl
--
--
-- Note: It's important to use the same conf (or at least the same port)
-- for bindPort and simpleHTTPWithSocket.
--
-- see also: bindPort, bindIPv4
simpleHTTPWithSocket :: (ToMessage a) => Socket -> Conf -> ServerPartT IO a -> IO ()
-- | Like simpleHTTP' with a socket.
simpleHTTPWithSocket' :: (ToMessage b, Monad m, Functor m) => (UnWebT m a -> UnWebT IO b) -> Socket -> Conf -> ServerPartT m a -> IO ()
-- | Bind port and return the socket for use with
-- simpleHTTPWithSocket. This function always binds to IPv4 ports
-- until Network module is fixed to support IPv6 in a portable way.
bindPort :: Conf -> IO Socket
-- | Bind to ip and port and return the socket for use with
-- simpleHTTPWithSocket.
--
-- -- import Happstack.Server -- -- main = do let conf = nullConf -- addr = "127.0.0.1" -- s <- bindIPv4 addr (port conf) -- simpleHTTPWithSocket s conf $ ok $ toResponse $ -- "now listening on ip addr " ++ addr ++ -- " and port " ++ show (port conf) --bindIPv4 :: String -> Int -> IO Socket -- | Parse command line options into a Conf. parseConfig :: [String] -> Either [String] Conf -- | Wait for a signal. On unix, a signal is sigINT or sigTERM (aka -- Control-C). -- -- On windows, the signal is entering: e return waitForTermination :: IO () -- | Filter for compressing the Response body. module Happstack.Server.Internal.Compression -- | reads the Accept-Encoding header. Then, if possible will -- compress the response body with methods gzip or -- deflate. -- -- 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 ())]
-- | 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 ())]
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]
-- | 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