1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use route_recognizer::{Match, Params, Router as MethodRouter};
use std::collections::HashMap;
use crate::endpoint::DynEndpoint;
use crate::{Request, Response, StatusCode};
#[allow(missing_debug_implementations)]
pub(crate) struct Router<State> {
method_map: HashMap<http_types::Method, MethodRouter<Box<DynEndpoint<State>>>>,
all_method_router: MethodRouter<Box<DynEndpoint<State>>>,
}
#[allow(missing_debug_implementations)]
pub(crate) struct Selection<'a, State> {
pub(crate) endpoint: &'a DynEndpoint<State>,
pub(crate) params: Params,
}
impl<State: Clone + Send + Sync + 'static> Router<State> {
pub(crate) fn new() -> Self {
Router {
method_map: HashMap::default(),
all_method_router: MethodRouter::new(),
}
}
pub(crate) fn add(
&mut self,
path: &str,
method: http_types::Method,
ep: Box<DynEndpoint<State>>,
) {
self.method_map
.entry(method)
.or_insert_with(MethodRouter::new)
.add(path, ep)
}
pub(crate) fn add_all(&mut self, path: &str, ep: Box<DynEndpoint<State>>) {
self.all_method_router.add(path, ep)
}
pub(crate) fn route(&self, path: &str, method: http_types::Method) -> Selection<'_, State> {
if let Some(Match { handler, params }) = self
.method_map
.get(&method)
.and_then(|r| r.recognize(path).ok())
{
Selection {
endpoint: &**handler,
params,
}
} else if let Ok(Match { handler, params }) = self.all_method_router.recognize(path) {
Selection {
endpoint: &**handler,
params,
}
} else if method == http_types::Method::Head {
self.route(path, http_types::Method::Get)
} else if self
.method_map
.iter()
.filter(|(k, _)| **k != method)
.any(|(_, r)| r.recognize(path).is_ok())
{
Selection {
endpoint: &method_not_allowed,
params: Params::new(),
}
} else {
Selection {
endpoint: ¬_found_endpoint,
params: Params::new(),
}
}
}
}
async fn not_found_endpoint<State: Clone + Send + Sync + 'static>(
_req: Request<State>,
) -> crate::Result {
Ok(Response::new(StatusCode::NotFound))
}
async fn method_not_allowed<State: Clone + Send + Sync + 'static>(
_req: Request<State>,
) -> crate::Result {
Ok(Response::new(StatusCode::MethodNotAllowed))
}