Copyright | (c) 2015 Athan Clark |
---|---|
License | BSD-style |
Maintainer | athan.clark@gmail.com |
Stability | experimental |
Portability | GHC |
Safe Haskell | None |
Language | Haskell2010 |
This module exports most of what you'll need for sophisticated routing -
all the tools from wai-middleware-verbs
(routing for the incoming HTTP method) and
wai-middleware-content-type
(routing for the incoming Accept header, and implied file extension),
WAI itself, and
wai-transformers - some simple
type aliases wrapped around WAI's Application
and Middleware
types, allowing us
to embed monad transformer stacks for our applications.
To match a route, you have a few options - you can match against a string literal, a regular expression (via regex-compat), or an attoparsec parser. This list will most likely grow in the future, depending on demand.
There is also support for embedding security layers in your routes, in the same
nested manner. By "tagging" a set of routes with an authorization role (with auth
),
you populate a list of roles breached during any request. The function argument to
routeAuth
guards a Request to pass or fail at the high level, while auth
lets
you create your authorization boundaries on a case-by-case basis. Both allow
you to tap into the monad transformer stack for logging, STM variables, database queries,
etc.
- match :: (Monad m, Singleton (UrlChunks xs) childContent (RootedPredTrie Text resultContent), cleanxs ~ CatMaybes xs, ArityTypeListIso childContent cleanxs resultContent) => UrlChunks xs -> childContent -> HandlerT resultContent sec m ()
- matchHere :: Monad m => content -> HandlerT content sec m ()
- matchAny :: Monad m => content -> HandlerT content sec m ()
- matchGroup :: (Monad m, cleanxs ~ CatMaybes xs, ExtrudeSoundly cleanxs xs childContent resultContent, ExtrudeSoundly cleanxs xs childSec resultSec) => UrlChunks xs -> HandlerT childContent childSec m () -> HandlerT resultContent resultSec m ()
- auth :: Monad m => sec -> AuthScope -> HandlerT content (SecurityToken sec) m ()
- route :: Monad m => HandlerT (MiddlewareT m) sec m a -> MiddlewareT m
- routeAuth :: (Monad m, MonadThrow m) => (Request -> [sec] -> m ()) -> HandlerT (MiddlewareT m) (SecurityToken sec) m a -> MiddlewareT m
- extractMatch :: Monad m => [Text] -> HandlerT r sec m a -> m (Maybe r)
- extractMatchAny :: Monad m => [Text] -> HandlerT r sec m a -> m (Maybe r)
- extractAuthSym :: Monad m => [Text] -> HandlerT x (SecurityToken sec) m a -> m [sec]
- extractAuth :: (Monad m, MonadThrow m) => (Request -> [sec] -> m ()) -> Request -> HandlerT x (SecurityToken sec) m a -> m ()
- extractNearestVia :: Monad m => [Text] -> (HandlerT r sec m a -> m (RootedPredTrie Text r)) -> HandlerT r sec m a -> m (Maybe r)
- data SecurityToken s = SecurityToken {
- securityToken :: !s
- securityScope :: !AuthScope
- data AuthScope
- module Web.Routes.Nested.Match
- module Web.Routes.Nested.Types
Combinators
match :: (Monad m, Singleton (UrlChunks xs) childContent (RootedPredTrie Text resultContent), cleanxs ~ CatMaybes xs, ArityTypeListIso childContent cleanxs resultContent) => UrlChunks xs -> childContent -> HandlerT resultContent sec m () Source
Embed a MiddlewareT
into a set of routes via a matching string. You should
expect the match to create arity in your handler - the childContent
variable.
The arity of childContent
may grow or shrink, depending on the heterogeneous
list created from the list of parsers, regular expressions, or arbitrary predicates
in the order written - so something like:
match (p_ "double-parser" double </> o_) handler
...then handler
must have arity Double ->
. If this
route was at the top level, then the total arity must be Double -> MiddlewareT m
.
Generally, if the routes you are building get grouped
by a predicate with matchGroup
,
then we would need another level of arity before the Double
.
matchHere :: Monad m => content -> HandlerT content sec m () Source
Create a handle for the current route - an alias for h -> match o_ h
.
matchAny :: Monad m => content -> HandlerT content sec m () Source
Match against any route, as a last resort against all failing matches -
use this for a catch-all at some level in their routes, something
like a not-found 404
page is useful.
matchGroup :: (Monad m, cleanxs ~ CatMaybes xs, ExtrudeSoundly cleanxs xs childContent resultContent, ExtrudeSoundly cleanxs xs childSec resultSec) => UrlChunks xs -> HandlerT childContent childSec m () -> HandlerT resultContent resultSec m () Source
Prepends a common route to an existing set of routes. You should note that doing this with a parser or regular expression will necessitate the existing arity in the handlers before the progam can compile.
auth :: Monad m => sec -> AuthScope -> HandlerT content (SecurityToken sec) m () Source
Sets the security role and error handler for a set of routes, optionally including its parent route.
Routing
routeAuth :: (Monad m, MonadThrow m) => (Request -> [sec] -> m ()) -> HandlerT (MiddlewareT m) (SecurityToken sec) m a -> MiddlewareT m Source
extractMatch :: Monad m => [Text] -> HandlerT r sec m a -> m (Maybe r) Source
extractMatchAny :: Monad m => [Text] -> HandlerT r sec m a -> m (Maybe r) Source
Extracts only the notFound
responses
extractAuthSym :: Monad m => [Text] -> HandlerT x (SecurityToken sec) m a -> m [sec] Source
Find the security tokens / authorization roles affiliated with a request for a set of routes.
extractAuth :: (Monad m, MonadThrow m) => (Request -> [sec] -> m ()) -> Request -> HandlerT x (SecurityToken sec) m a -> m () Source
Extracts only the security handling logic, and turns it into a guard
extractNearestVia :: Monad m => [Text] -> (HandlerT r sec m a -> m (RootedPredTrie Text r)) -> HandlerT r sec m a -> m (Maybe r) Source
Given a way to draw out a special-purpose trie from our route set, route to the responses based on a furthest-reached method.
Metadata
data SecurityToken s Source
Use a custom security token type and an AuthScope
to define
where and what kind of security should take place.
SecurityToken | |
|
Show s => Show (SecurityToken s) Source |
Designate the scope of security to the set of routes - either only the adjacent routes, or the adjacent and the parent container node (root node if not declared).
Re-Exports
module Web.Routes.Nested.Match
module Web.Routes.Nested.Types