Safe Haskell | None |
---|---|
Language | Haskell2010 |
The basic routing API, sufficient for route and routing map construction. There is usually no need to import this module directly as it is re-exported by most other exposed interfaces.
This package supports route construction as follows:
Endpoint specification, which consists of a
Route
key and action value.- Describe the parameters of each endpoint using
Route
, which is constructed by composing theroute*
functions (routeHost
,routePath
,routeMethod
,routeQuery
, etc.) using Control.Invertible.Monoidal operators. Typically these predicates should be specified in order for sensible routing, but you can also usenormRoute
to reorder them automatically. - Join the route with a target using
`RouteAction`
. This target action is the value associated with the route key, and is usually an action to produce a response in your preferred framework (but could be anything). - The
RouteAction
should typically be assigned to a top-level variable. While the type of theRoute
parameter can differ for each route, all action values must have the same result type.
getThing ::
RouteAction
Int (IO Response) getThing =routePath
("thing" *<parameter
) >*routeMethod
GET `RouteAction` \thingId -> do return Response{..} postThingValue ::RouteAction
(Int, String) (IO Response) postThingValue =routeSecure
True *<routePath
("thing" *<parameter
>* "value" >*<parameter
) >*routeMethod
POSTRouteAction
\(thingId, attribute) -> set thingId attribute =<< getRequestBody return Response{..}- Describe the parameters of each endpoint using
Route Map specification.
- Apply each of the
RouteAction
s in your program torouteCase
(orrouteNormCase
-- seenormRoute
). - Apply
routes
to a list of the resultingRouteCase
s to form aRouteMap
.
myRoutes =
routes
[routeCase
getThing ,routeCase
postThingValue , .. ]- Apply each of the
You can also add support for new parameter types by creating your own instances of Parameter
.
Synopsis
- data Route a
- routeHost :: Host h -> Route h
- routeSecure :: Bool -> Route ()
- routePath :: Path p -> Route p
- routeMethod :: IsMethod m => m -> Route ()
- routeMethods :: (Eq m, IsMethod m) => [m] -> Route m
- routeQuery :: QueryString -> Placeholder QueryString a -> Route a
- routeAccept :: ContentType -> Route ()
- routeAccepts :: [ContentType] -> Route ContentType
- routeCustom :: Typeable a => (Request -> Maybe a) -> (a -> Request -> Request) -> Route a
- routePriority :: Int -> Route ()
- data RouteAction a b = RouteAction {
- actionRoute :: !(Route a)
- routeAction :: !(a -> b)
- mapActionRoute :: (a <-> b) -> RouteAction a r -> RouteAction b r
- data Host a
- data Path a
- class IsMethod m
- type QueryString = ByteString
- type ContentType = ByteString
- module Control.Invertible.Monoidal
- wildcard :: (Parameterized s f, MonoidalAlt f, Parameter s a) => [a] -> f ()
- class (Eq s, IsString s, Hashable s, Monoid s) => RouteString s
- class (RouteString s, Typeable a) => Parameter s a where
- parseParameter :: s -> Maybe a
- renderParameter :: a -> s
- class Parameterized s p | p -> s
- parameter :: (Parameterized s p, Parameter s a) => p a
- param :: (Parameterized s p, Parameter s a) => a -> p a
- data Placeholder s a
- type RouteCase = RouteMapT ((->) Dynamics)
- routeCase :: RouteAction a b -> RouteCase b
- routeNormCase :: RouteAction a b -> RouteCase b
- type RouteMap = RouteCase
- routes :: [RouteCase a] -> RouteMap a
- fallbackHEADtoGET :: RouteMap a -> RouteMap a
Route construction
A Monoidal
collection of routing predicates.
For example:
routeHost ("www" >* "domain.com") *< routePath ("object" *< parameter) :: Route Int
routeSecure :: Bool -> Route () Source #
Limit a route to only secure (https:) or insecure (http:) protocols. By default, routes apply to both.
routePath :: Path p -> Route p Source #
Limit a route to matching paths.
By default, routes apply to any paths not matched by any other routes in the map (e.g., 404 handler, though it can be more general to handle a RouteNotFound
result directly) that also match all previous predicates.
routeMethod :: IsMethod m => m -> Route () Source #
Limit a route to a method. By default, routes apply to all methods not handled by any other routes for the same earlier matching predicates (e.g., within the same path).
routeMethods :: (Eq m, IsMethod m) => [m] -> Route m Source #
Limit a route to a list of methods and return that method. Supplying a method not in this list when generating (reverse) routes will result in a run-time error.
routeQuery :: QueryString -> Placeholder QueryString a -> Route a Source #
Limit a route to requests with a matching URL query parameter. By default, other routes match only when the given parameter is missing.
routeAccept :: ContentType -> Route () Source #
Limit a route to requests with the given "Content-type" header, i.e., POST requests containing a request body of a certain type. Note that this does not relate to the type of the response or the "Accept" header. By default, routes match only requests without bodies or with content-type headers not matched by any other routes.
routeAccepts :: [ContentType] -> Route ContentType Source #
Limit a route to a list of methods and return that method. Supplying a method not in this list when generating (reverse) routes will result in a run-time error.
routeCustom :: Typeable a => (Request -> Maybe a) -> (a -> Request -> Request) -> Route a Source #
A custom routing predicate that can perform arbitrary tests on the request and reverse routing.
The first argument is used in forward routing to check the request, and only passes if it returns Just
.
The second argument is used in reverse routing to modify the request according to the parameter.
By default, routes match all requests -- unlike other predicates, matching a custom rule does not exclude other routes.
This should be used sparingly and towards the end of a route as, unlike most other predicates, it only provides O(n) lookups, as these functions must be called for every route candidate (those where all previous predicates match).
routePriority :: Int -> Route () Source #
Set the priority of a route. Routes with higher priority take precedence when there is a conflict.
By default, routes have priority 0.
When combining (with routes
) or normalizing (with normRoute
) routes, this has the lowest precedence (so that conflicts are handled only after matching all other predicates).
data RouteAction a b infix 1 Source #
Specify the action to take for a given route, often used as an infix operator between the route specification and the function used to produce the result (which usually generates the HTTP response, but could be anything).
RouteAction infix 1 | |
|
Instances
Functor (RouteAction a) Source # | |
Defined in Web.Route.Invertible.Route fmap :: (a0 -> b) -> RouteAction a a0 -> RouteAction a b # (<$) :: a0 -> RouteAction a b -> RouteAction a a0 # |
mapActionRoute :: (a <-> b) -> RouteAction a r -> RouteAction b r Source #
RouteAction
is invariant in its first argument.
Apply a bijection to the routing argument, leaving the action alone.
Supporting types
A hostname matcher.
These should typically be constructed using the IsString
and Parameterized
instances.
This matches hostnames in reverse order (from TLD down), but the Monoidal
instance and splitHost
automatically deal with this for you.
Example:
parameter >* "domain" >* "com" :: Host String
matches (or generates) *.domain.com
and returns the *
component.
Instances
Monoidal Host Source # | |
MonoidalAlt Host Source # | |
Functor Host Source # | |
Parameterized HostString Host Source # | |
Defined in Web.Route.Invertible.Host | |
Show (Host a) Source # | |
IsString (Host ()) Source # | Since domain components cannot contain ".", |
Defined in Web.Route.Invertible.Host fromString :: String -> Host () # |
A URL path parser/generator.
These should typically be constructed using the IsString
and Parameterized
instances.
Note that the individual components are decoded path segments, so a literal slash in a component (e.g., as produced with fromString
) will match "%2F".
Example:
"get" *< parameter >*< "value" *< parameter :: Path (String, Int)
matches (or generates) /get/$x/value/$y
for any string $x
and any int $y
and returns those values.
Any types that represent an HTTP method.
Instances
IsMethod ByteString Source # | |
Defined in Web.Route.Invertible.Method toMethod :: ByteString -> Method Source # fromMethod :: Method -> Maybe ByteString Source # | |
IsMethod StdMethod Source # | |
IsMethod Method Source # | |
IsMethod Method Source # | |
IsMethod (Either ByteString StdMethod) Source # | |
Defined in Web.Route.Invertible.Method toMethod :: Either ByteString StdMethod -> Method Source # fromMethod :: Method -> Maybe (Either ByteString StdMethod) Source # |
type QueryString = ByteString Source #
The type of URL query strings, variables, and parameters, after URI decoding but before UTF-8 decoding.
type ContentType = ByteString Source #
String representation of content types, e.g., from HTTP "Content-type" headers.
Parser construction
module Control.Invertible.Monoidal
wildcard :: (Parameterized s f, MonoidalAlt f, Parameter s a) => [a] -> f () Source #
Ignore an arbitrary sequence of parameters (usually as a tail), always generating the same thing.
Placeholder parameters
class (Eq s, IsString s, Hashable s, Monoid s) => RouteString s Source #
Representions of request data that can be used in routing
Instances
RouteString String Source # | |
RouteString ByteString Source # | |
Defined in Web.Route.Invertible.String toString :: ByteString -> String Source # | |
RouteString Text Source # | |
class (RouteString s, Typeable a) => Parameter s a where Source #
A parameter value a
that can be parsed from or rendered into string data s
.
parseParameter
must invert renderParameter
:
parseParameter . renderParameter == Just
Nothing
parseParameter :: s -> Maybe a Source #
Parse string data into a value.
Often equivalent (and defaults) to readMaybe
.
default parseParameter :: Read a => s -> Maybe a Source #
renderParameter :: a -> s Source #
Render a value into a string.
Often equivalent (and defaults) to show
.
default renderParameter :: Show a => a -> s Source #
Instances
class Parameterized s p | p -> s Source #
Parsers p
that operate over string data s
, and so can parse placeholder Parameter
values.
Instances
Parameterized PathString Path Source # | |
Defined in Web.Route.Invertible.Path | |
Parameterized HostString Host Source # | |
Defined in Web.Route.Invertible.Host | |
RouteString s => Parameterized s (Placeholder s) Source # | |
Defined in Web.Route.Invertible.Placeholder parameter :: Parameter s a => Placeholder s a Source # | |
Parameterized s (Sequence s) Source # | |
parameter :: (Parameterized s p, Parameter s a) => p a Source #
Create a parser for a parameter of type a
.
param :: (Parameterized s p, Parameter s a) => a -> p a Source #
Create a placeholder parameter
with the type of the argument, which is ignored.
data Placeholder s a Source #
A segment of a parser over strings s
, which may be a fixed string (usually created through IsString
), only accepting a single fixed value, or a dynamic parameter (created through Parameterized
), which encapsulates a Parameter
type.
Instances
Forward routing
routeCase :: RouteAction a b -> RouteCase b Source #
Convert a Route
and result generator to a single entry in the routing table.
routeNormCase :: RouteAction a b -> RouteCase b Source #
type RouteMap = RouteCase Source #
A map for efficiently looking up requests based on a set of individual route specifications.
fallbackHEADtoGET :: RouteMap a -> RouteMap a Source #
Make any handler for a GET
method in the map also apply to HEAD
requests, provided there is not an existing handler.
A number of frameworks can automatically convert your GET
responses into HEAD
responses, so this is useful (if slightly wasteful) in those cases.