1#![doc = include_str!("../docs/path.md")]
2
3use crate::make::MakeRouteMatcher;
4use crate::RouteMatcher;
5use async_trait::async_trait;
6use http::request::Parts;
7use matchit::Router;
8use satex_core::component::{Args, Configurable};
9use satex_core::extension::insert_url_params;
10use satex_core::util::With;
11use satex_core::Error;
12use satex_macro::make;
13
14#[make(kind = Path, shortcut_mode = Sequence)]
15struct MakePathRouteMatcher {
16 patterns: Vec<String>,
17}
18
19impl MakeRouteMatcher for MakePathRouteMatcher {
20 type Matcher = PathRouteMatcher;
21
22 fn make(&self, args: Args) -> Result<Self::Matcher, Error> {
23 Config::with_args(args)
24 .map_err(Error::new)
25 .and_then(|config| PathRouteMatcher::new(config.patterns))
26 }
27}
28
29pub struct PathRouteMatcher {
30 router: Router<()>,
31}
32
33impl PathRouteMatcher {
34 pub fn new<T: AsRef<str>, I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Error> {
35 iter.into_iter()
36 .try_fold(Router::new(), |router, pattern| {
37 router.try_with(|router| router.insert(pattern.as_ref(), ()))
38 })
39 .map_err(Error::new)
40 .map(|router| PathRouteMatcher { router })
41 }
42}
43
44#[async_trait]
45impl RouteMatcher for PathRouteMatcher {
46 async fn matches(&self, parts: &mut Parts) -> Result<bool, Error> {
47 let path = parts.uri.path();
48 match self.router.at(path) {
49 Ok(m) => {
50 insert_url_params(&mut parts.extensions, m.params);
51 Ok(true)
52 }
53 Err(_) => Ok(false),
54 }
55 }
56}