macro_rules! router {
($request:expr,
$(($method:ident) [$url_pattern:expr $(, $param:ident: $param_type:ty)*] => $handle:expr,)*
_ => $default:expr $(,)*) => { ... };
(__param_dispatch $request_url:ident, $url_pattern:expr => $handle:expr ; ) => { ... };
(__param_dispatch $request_url:ident, $url_pattern:expr => $handle:expr ; $($param:ident: $param_type:ty),*) => { ... };
(__check_url_match $request_url:ident, $url_pattern:expr => $handle:expr) => { ... };
(__check_parse_pattern $request_url_str:ident, $url_pattern:expr => $handle:expr ; $($param:ident: $param_type:ty),*) => { ... };
(__insert_param $request_url:ident, $url_params:ident, $key:expr, $actual:expr ; ) => { ... };
(__insert_param $request_url:ident, $url_params:ident, $key:expr, $actual:expr ; $param:tt: $param_type:tt $($params:tt: $param_types:tt)*) => { ... };
(__bind_url_param $url_params:ident, $actual:expr, $param:ident, $param_type:ty) => { ... };
(__build_resp $request_url:ident, $url_params:expr, $handle:expr ; ) => { ... };
(__build_resp $request_url:ident, $url_params:expr, $handle:expr ; $param:tt: $param_type:tt $($params:tt: $param_types:tt)*) => { ... };
(__bind_param $request_url:ident, $url_params:expr, $handle:expr, $param:ident: $param_type:ty ; $($params:tt: $param_types:tt)*) => { ... };
($request:expr, $(($method:ident) ($($pat:tt)+) => $value:block,)* _ => $def:expr $(,)*) => { ... };
(__check_pattern $url:ident $value:block /{$p:ident} $($rest:tt)*) => { ... };
(__check_pattern $url:ident $value:block /{$p:ident: $t:ty} $($rest:tt)*) => { ... };
(__check_pattern $url:ident $value:block /$p:ident $($rest:tt)*) => { ... };
(__check_pattern $url:ident $value:block - $($rest:tt)*) => { ... };
(__check_pattern $url:ident $value:block) => { ... };
(__check_pattern $url:ident $value:block /) => { ... };
(__check_pattern $url:ident $value:block $p:ident $($rest:tt)*) => { ... };
}
Expand description
Equivalent to a match
expression but for routes.
§Example
let _result = router!(request,
// first route
(GET) (/) => {
12
},
// second route
(GET) (/hello) => {
43 * 7
},
// ... other routes here ...
// default route
_ => 5
);
§Details
The macro will take each route one by one and execute the first one that matches, similar to the
match
language construct. The whole router!
expression then returns what the body
returns, therefore all the bodies must return the same type of data.
You can use parameters by putting them inside {}
:
(GET) (/{id}/foo) => {
...
},
If you use parameters inside {}
, then a variable with the same name will be available in the
code in the body.
Each parameter gets parsed through the FromStr
trait. If the parsing fails, the route is
ignored. If you get an error because the type of the parameter couldn’t be inferred, you can
also specify the type inside the brackets:
(GET) (/{id: u32}/foo) => {
...
},
§Alternative syntax (string-style)
You can also define url routes using strings. This allows using characters that are not valid rust
ident
s (e.g. periods and numbers).
(GET) ["/hello/2"] => { ... },
You can use parameters by putting them inside {}
, and adding an identity: type
pair. Note
that identity
names must match the parameter names used in the URL string and an
accompanying type
is required. The declared identities (variables) will be parsed through the
FromStr
trait and made available in the code of the route’s body. If the parsing fails, the
route is ignored.
(GET) ["/add/{a}/plus/{b}", a: u32, b: u32] => {
let c = a + b;
...
},
§Some other things to note
- The right of the
=>
must be a block (must be surrounded by{
and}
). - The default handler (with
_
) must be present or will get a compilation error. - The pattern of the URL must be inside parentheses for ident-style syntax and brackets for string-style syntax. This is to bypass limitations of Rust’s macros system.
- String-style and token-style definitions are mutually exclusive. Either all routes are defined with tokens or all routes are defined with strings.
- When using URL parameters with string-style syntax, the parameter names in the URL and
identity: type
pairs must be the same, e.g.... ["/users/{name}", name: String] ...
. This can’t be checked at compile time so bad route definitions will cause a runtimepanic
.