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
use std::sync::Arc;
use log::error;
use crate::http::*;
use crate::utils::{RequestContinuation, UriPathMatcher};
use crate::utils::RequestContinuation::*;
pub struct Builder {
stack: Vec<(MiddlewareRule, Box<Middleware>)>,
}
impl Builder {
pub fn new() -> Self {
Builder {
stack: Vec::new()
}
}
pub fn apply<M: 'static + Middleware>(mut self, m: M, include_path: Vec<&str>, exclude_path: Option<Vec<&str>>) -> Self {
let rule = MiddlewareRule::new(include_path, exclude_path);
let boxed_m = Box::new(m);
self.stack.push((rule, boxed_m));
self
}
pub fn build(self) -> MiddlewareStack {
let Builder {
stack,
} = self;
MiddlewareStack {
middlewares: Arc::new(stack),
}
}
}
pub struct MiddlewareStack {
middlewares: Arc<Vec<(MiddlewareRule, Box<Middleware>)>>
}
impl MiddlewareStack {
pub fn new() -> Self {
MiddlewareStack {
middlewares: Arc::new(Vec::new())
}
}
pub fn resolve(&self, req: &mut SyncRequest, res: &mut SyncResponse) -> RequestContinuation {
for &(ref rule, ref middleware) in self.middlewares.iter() {
if rule.validate_path(req.uri().path()) {
if let Stop = middleware.resolve(req, res) {
return Stop;
}
}
}
Continue
}
}
impl Clone for MiddlewareStack {
fn clone(&self) -> Self {
MiddlewareStack {
middlewares: self.middlewares.clone(),
}
}
}
pub trait Middleware: Send + Sync {
fn resolve(&self, req: &mut SyncRequest, res: &mut SyncResponse) -> RequestContinuation;
}
struct MiddlewareRule {
included_path: Vec<UriPathMatcher>,
excluded_path: Option<Vec<UriPathMatcher>>,
}
impl MiddlewareRule {
pub fn new(include_path: Vec<&str>, exclude_path: Option<Vec<&str>>) -> Self {
MiddlewareRule {
included_path: include_path.iter().filter_map(|p| UriPathMatcher::new(p).map_err(|e| error!("Unable to construct included middleware route: {}", e)).ok()).collect(),
excluded_path: exclude_path.map(|ex| ex.iter().filter_map(|p| UriPathMatcher::new(p).map_err(|e| error!("Unable to construct excluded middleware route: {}", e)).ok()).collect()),
}
}
pub fn validate_path(&self, path: &str) -> bool {
if self.included_path.iter().any(|m_p| m_p.match_start(path)) {
if let Some(ref excluded_path) = self.excluded_path {
return !excluded_path.iter().any(|m_e_p| m_e_p.match_start(path));
} else {
return true;
}
}
false
}
}