Safe Haskell | Trustworthy |
---|---|
Language | Haskell2010 |
Web.Simple.Controller
Contents
Description
Controller
provides a convenient syntax for writting Application
code as a Monadic action with access to an HTTP request as well as app
specific data (e.g. a database connection pool, app configuration etc.)
This module also defines some
helper functions that leverage this feature. For example, redirectBack
reads the underlying request to extract the referer and returns a redirect
response:
myController = do ... if badLogin then redirectBack else ...
- type Controller s = ControllerT s IO
- newtype ControllerT s m a = ControllerT {
- runController :: s -> Request -> m (Either Response a, s)
- controllerApp :: s -> Controller s a -> Application
- controllerState :: Controller s s
- putState :: s -> Controller s ()
- request :: Controller s Request
- localRequest :: (Request -> Request) -> Controller s a -> Controller s a
- respond :: Response -> Controller s a
- requestHeader :: HeaderName -> Controller s (Maybe ByteString)
- routeHost :: ByteString -> Controller s a -> Controller s ()
- routeTop :: Controller s a -> Controller s ()
- routeMethod :: StdMethod -> Controller s a -> Controller s ()
- routeAccept :: ByteString -> Controller s a -> Controller s ()
- routePattern :: Text -> Controller s a -> Controller s ()
- routeName :: Text -> Controller s a -> Controller s ()
- routeVar :: Text -> Controller s a -> Controller s ()
- class Parseable a
- queryParam :: Parseable a => ByteString -> Controller s (Maybe a)
- queryParam' :: Parseable a => ByteString -> Controller s a
- queryParams :: Parseable a => ByteString -> Controller s [a]
- readQueryParam :: Read a => ByteString -> Controller s (Maybe a)
- readQueryParam' :: Read a => ByteString -> Controller s a
- readQueryParams :: Read a => ByteString -> Controller s [a]
- parseForm :: Controller s ([Param], [(ByteString, FileInfo ByteString)])
- redirectBack :: Controller s a
- redirectBackOr :: Response -> Controller s a
- data ControllerException
- body :: Controller s ByteString
- hoistEither :: Either Response a -> Controller s a
Example
The most basic Routeable
types are Application
and Response
. Reaching
either of these types marks a termination in the routing lookup. This module
exposes a monadic type Route
which makes it easy to create routing logic
in a DSL-like fashion.
Route
s are concatenated using the >>
operator (or using do-notation).
In the end, any Routeable
, including a Route
is converted to an
Application
and passed to the server using mkRoute
:
mainAction :: Controller () () mainAction = ... signinForm :: Controller () () signinForm req = ... login :: Controller () () login = ... updateProfile :: Controller () () updateProfile = ... main :: IO () main = run 3000 $ controllerApp () $ do routeTop mainAction routeName "sessions" $ do routeMethod GET signinForm routeMethod POST login routeMethod PUT $ routePattern "users/:id" updateProfile routeAll $ responseLBS status404 [] "Are you in the right place?"
type Controller s = ControllerT s IO Source
newtype ControllerT s m a Source
The ControllerT Monad is both a State-like monad which, when run, computes
either a Response
or a result. Within the ControllerT Monad, the remainder
of the computation can be short-circuited by respond
ing with a Response
.
Constructors
ControllerT | |
Fields
|
Instances
(Applicative m, Monad m, MonadBase m m) => MonadBase m (ControllerT s m) | |
MonadBaseControl m m => MonadBaseControl m (ControllerT s m) | |
Monad m => MonadReader Request (ControllerT s m) | |
Monad m => MonadState s (ControllerT s m) | |
MonadTrans (ControllerT s) | |
(Functor m, Monad m) => Alternative (ControllerT s m) | |
Monad m => Monad (ControllerT s m) | |
Functor m => Functor (ControllerT s m) | |
Monad m => MonadPlus (ControllerT s m) | |
(Monad m, Functor m) => Applicative (ControllerT s m) | |
MonadIO m => MonadIO (ControllerT s m) | |
data StM (ControllerT s m) = StCtrl (Either Response a, s) |
controllerApp :: s -> Controller s a -> Application Source
Convert the controller into an Application
controllerState :: Controller s s Source
Extract the application-specific state
putState :: s -> Controller s () Source
request :: Controller s Request Source
Extract the request
localRequest :: (Request -> Request) -> Controller s a -> Controller s a Source
Modify the request for the given computation
respond :: Response -> Controller s a Source
Provide a response
respond r >>= f === respond r
requestHeader :: HeaderName -> Controller s (Maybe ByteString) Source
Returns the value of the given request header or Nothing
if it is not
present in the HTTP request.
Common Routes
routeHost :: ByteString -> Controller s a -> Controller s () Source
Matches on the hostname from the Request
. The route only succeeds on
exact matches.
routeTop :: Controller s a -> Controller s () Source
routeMethod :: StdMethod -> Controller s a -> Controller s () Source
routeAccept :: ByteString -> Controller s a -> Controller s () Source
Matches if the request's Content-Type exactly matches the given string
routePattern :: Text -> Controller s a -> Controller s () Source
Routes the given URL pattern. Patterns can include
directories as well as variable patterns (prefixed with :
) to be added
to queryString
(see routeVar
)
- /posts/:id
- /posts/:id/new
- /:date/posts/:category/new
routeName :: Text -> Controller s a -> Controller s () Source
Matches if the first directory in the path matches the given ByteString
routeVar :: Text -> Controller s a -> Controller s () Source
Always matches if there is at least one directory in pathInfo
but and
adds a parameter to queryString
where the key is the first parameter and
the value is the directory consumed from the path.
Inspecting query
The class of types into which query parameters may be converted
Minimal complete definition
Arguments
:: Parseable a | |
=> ByteString | Parameter name |
-> Controller s (Maybe a) |
Looks up the parameter name in the request's query string and returns the
Parseable
value or Nothing
.
For example, for a request with query string: "?foo=bar&baz=7",
queryParam "foo"
would return Just "bar"
, but
queryParam "zap"
would return Nothing
.
queryParam' :: Parseable a => ByteString -> Controller s a Source
Like queryParam
, but throws an exception if the parameter is not present.
queryParams :: Parseable a => ByteString -> Controller s [a] Source
Selects all values with the given parameter name
Arguments
:: Read a | |
=> ByteString | Parameter name |
-> Controller s (Maybe a) |
Like queryParam
, but further processes the parameter value with read
.
If that conversion fails, an exception is thrown.
Arguments
:: Read a | |
=> ByteString | Parameter name |
-> Controller s a |
Like readQueryParam
, but throws an exception if the parameter is not present.
Arguments
:: Read a | |
=> ByteString | Parameter name |
-> Controller s [a] |
Like queryParams
, but further processes the parameter values with read
.
If any read-conversion fails, an exception is thrown.
parseForm :: Controller s ([Param], [(ByteString, FileInfo ByteString)]) Source
Parses a HTML form from the request body. It returns a list of Param
s as
well as a list of File
s, which are pairs mapping the name of a file form
field to a FileInfo
pointing to a temporary file with the contents of the
upload.
myControllerT = do (prms, files) <- parseForm let mPicFile = lookup "profile_pic" files case mPicFile of Just (picFile) -> do sourceFile (fileContent picFile) $$ sinkFile ("images/" ++ (fileName picFile)) respond $ redirectTo "/" Nothing -> redirectBack
Redirection via referrer
redirectBack :: Controller s a Source
Redirect back to the referer. If the referer header is not present
redirect to root (i.e., /
).
Arguments
:: Response | Fallback response |
-> Controller s a |
Redirect back to the referer. If the referer header is not present
fallback on the given Response
.
Exception handling
Low-level utilities
body :: Controller s ByteString Source
Reads and returns the body of the HTTP request.
hoistEither :: Either Response a -> Controller s a Source