use crate::route_handler::{HandlerAction, Params, RequestInfo, RouteHandler};
pub struct Router {
inner: matchit::Router<Box<dyn RouteHandler>>,
}
impl Router {
pub fn new() -> Self {
Self {
inner: matchit::Router::new(),
}
}
pub fn route(mut self, path: &str, handler: impl RouteHandler + 'static) -> Self {
self.inner
.insert(path, Box::new(handler))
.expect("conflicting route");
self
}
pub async fn dispatch(&self, req: &RequestInfo<'_>) -> Option<HandlerAction> {
let matched = self.inner.at(req.path).ok()?;
let params = Params::from_matchit(&matched.params);
let req_with_params = RequestInfo {
params,
method: req.method,
path: req.path,
query: req.query,
headers: req.headers,
source_ip: req.source_ip,
signing_path: req.signing_path,
signing_query: req.signing_query,
};
matched
.value
.handle(&req_with_params)
.await
.map(HandlerAction::Response)
}
}
impl Default for Router {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
#[test]
fn matchit_catchall_does_not_match_root() {
let mut router = matchit::Router::<&str>::new();
router.insert("/{*path}", "handler").unwrap();
assert!(router.at("/").is_err());
}
#[test]
fn explicit_root_route_matches() {
let mut router = matchit::Router::<&str>::new();
router.insert("/", "root").unwrap();
assert!(router.at("/").is_ok());
}
}