afire/
route.rs

1use std::fmt::{self, Debug};
2use std::rc::Rc;
3use std::sync::Arc;
4
5use crate::{path::Path, Method, Request, Response};
6
7type StatelessRoute = Box<dyn Fn(&Request) -> Response + Send + Sync>;
8type StatefulRoute<State> = Box<dyn Fn(Arc<State>, &Request) -> Response + Send + Sync>;
9
10pub enum RouteType<State> {
11    Stateless(StatelessRoute),
12    Stateful(StatefulRoute<State>),
13}
14
15/// Defines a route.
16///
17/// You should not use this directly.
18/// It will be created automatically when using [`crate::Server::route`] or [`crate::Server::stateful_route`].
19#[derive(Debug)]
20pub struct Route<State> {
21    /// Route Method (GET, POST, ANY, etc.)
22    method: Method,
23
24    /// Route path, in its tokenized form.
25    path: Path,
26
27    /// Route Handler, either stateless or stateful.
28    pub(crate) handler: RouteType<State>,
29}
30
31impl<State> Route<State> {
32    /// Creates a new route.
33    pub(crate) fn new(method: Method, path: String, handler: StatelessRoute) -> Self {
34        Self {
35            method,
36            path: Path::new(path),
37            handler: RouteType::Stateless(handler),
38        }
39    }
40
41    /// Create a new stateful route
42    pub(crate) fn new_stateful(
43        method: Method,
44        path: String,
45        handler: StatefulRoute<State>,
46    ) -> Self {
47        Self {
48            method,
49            path: Path::new(path),
50            handler: RouteType::Stateful(handler),
51        }
52    }
53
54    /// Checks if the route is stateful.
55    pub(crate) fn is_stateful(&self) -> bool {
56        matches!(self.handler, RouteType::Stateful(_))
57    }
58
59    /// Checks if a Request matches the route.
60    /// Returns the path parameters if it does.
61    pub(crate) fn matches(&self, req: Rc<Request>) -> Option<Vec<(String, String)>> {
62        if self.method != Method::ANY && self.method != req.method {
63            return None;
64        }
65        self.path.match_path(req.path.clone())
66    }
67}
68
69impl<State> Debug for RouteType<State> {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        match self {
72            RouteType::Stateless(_) => f.write_str("stateless"),
73            RouteType::Stateful(_) => f.write_str("stateful"),
74        }
75    }
76}