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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use helpers::http::PercentDecoded;
use hyper::Body;
use router::route::Route;
use router::tree::node::Node;
use router::tree::segment::{SegmentMapping, SegmentType};
pub mod node;
pub mod regex;
pub mod segment;
pub struct Tree {
root: Node,
}
impl Tree {
pub fn new() -> Self {
trace!(" creating new tree");
Tree {
root: Node::new("/", SegmentType::Static),
}
}
pub fn add_child(&mut self, child: Node) {
self.root.add_child(child);
}
pub fn add_route(&mut self, route: Box<Route<ResBody = Body> + Send + Sync>) {
self.root.add_route(route);
}
pub fn borrow_root_mut(&mut self) -> &mut Node {
&mut self.root
}
pub fn has_child(&self, segment: &str, segment_type: SegmentType) -> bool {
self.root.has_child(segment, segment_type)
}
pub(crate) fn traverse<'a>(
&'a self,
req_path_segments: &'a [PercentDecoded],
) -> Option<(&Node, SegmentMapping<'a>, usize)> {
trace!(" starting tree traversal");
self.root.match_node(req_path_segments)
}
}
#[cfg(test)]
mod tests {
use hyper::{Method, Response, StatusCode};
use extractor::{NoopPathExtractor, NoopQueryStringExtractor};
use helpers::http::request::path::RequestPathSegments;
use helpers::http::response::create_empty_response;
use pipeline::set::*;
use router::route::dispatch::DispatcherImpl;
use router::route::matcher::MethodOnlyRouteMatcher;
use router::route::{Delegation, Extractors, RouteImpl};
use state::State;
use super::*;
fn handler(state: State) -> (State, Response<Body>) {
let res = create_empty_response(&state, StatusCode::OK);
(state, res)
}
#[test]
fn tree_traversal_tests() {
let pipeline_set = finalize_pipeline_set(new_pipeline_set());
let mut tree = Tree::new();
let mut activate_node_builder = Node::new("activate", SegmentType::Static);
let mut thing_node_builder = Node::new("thing", SegmentType::Dynamic);
let thing_route = {
let methods = vec![Method::GET];
let matcher = MethodOnlyRouteMatcher::new(methods);
let dispatcher = Box::new(DispatcherImpl::new(|| Ok(handler), (), pipeline_set));
let extractors: Extractors<NoopPathExtractor, NoopQueryStringExtractor> =
Extractors::new();
let route = RouteImpl::new(matcher, dispatcher, extractors, Delegation::Internal);
Box::new(route)
};
thing_node_builder.add_route(thing_route);
activate_node_builder.add_child(thing_node_builder);
tree.add_child(activate_node_builder);
let request_path_segments = RequestPathSegments::new("/%61ctiv%61te/workflow5");
match tree.traverse(request_path_segments.segments().as_slice()) {
Some((node, params, processed)) => {
assert!(node.is_routable());
assert_eq!(processed, 2);
assert_eq!(
params.get("thing").unwrap().last().unwrap().as_ref(),
"workflow5"
);
}
None => panic!(),
}
assert!(
tree.traverse(&[PercentDecoded::new("/").unwrap()])
.is_none()
);
assert!(
tree.traverse(&[PercentDecoded::new("/activate").unwrap()])
.is_none()
);
}
}