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
extern crate iron;
use iron::prelude::*;
use iron::modifier::Modifier;
use std::collections::HashMap;
use std::collections::hash_map;
trait ModifierInner: Send + Sync {
fn clone_box(&self) -> Box<ModifierInner>;
fn apply_modify(self: Box<Self>, res: &mut Response);
}
impl<M: Modifier<Response> + Send + Sync + Clone + 'static> ModifierInner for M {
fn clone_box(&self) -> Box<ModifierInner> {
Box::new(self.clone())
}
fn apply_modify(self: Box<Self>, res: &mut Response) { self.modify(res) }
}
impl Modifier<Response> for Box<ModifierInner> {
fn modify(self, res: &mut Response) { self.apply_modify(res) }
}
enum Target {
AfterMiddleware(Box<iron::middleware::AfterMiddleware>),
Modifier(Box<ModifierInner>),
Handler(Box<iron::Handler>),
}
impl iron::middleware::AfterMiddleware for Target {
fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
match *self {
Target::AfterMiddleware(ref x) => x.after(req, res),
Target::Modifier(ref x) => Ok(res.set(x.clone_box())),
Target::Handler(ref x) => x.handle(req)
}
}
fn catch(&self, req: &mut Request, mut err: IronError) -> IronResult<Response> {
match *self {
Target::AfterMiddleware(ref x) => x.catch(req, err),
Target::Modifier(ref x) => { err.response.set_mut(x.clone_box()); Err(err) },
Target::Handler(ref x) => x.handle(req)
}
}
}
pub struct ErrorRouter {
by_status: HashMap<iron::status::Status, Target>
}
impl Default for ErrorRouter {
fn default() -> ErrorRouter { ErrorRouter { by_status: HashMap::new() } }
}
impl ErrorRouter {
pub fn new() -> Self { ErrorRouter::default() }
fn register(&mut self, status: iron::status::Status, target: Target) {
match self.by_status.entry(status) {
hash_map::Entry::Occupied(_) => panic!("Target for {:?} already registered.", status),
hash_map::Entry::Vacant(x) => x.insert(target)
};
}
pub fn handle_status<T: iron::Handler>(&mut self, status: iron::status::Status, handler: T) {
self.register(status, Target::Handler(Box::new(handler)))
}
pub fn after_status<T: iron::middleware::AfterMiddleware>
(&mut self, status: iron::status::Status, middleware: T) {
self.register(status, Target::AfterMiddleware(Box::new(middleware)))
}
pub fn modifier_for_status<T: Modifier<Response> + Send + Sync + Clone + 'static>
(&mut self, status: iron::status::Status, modifier: T) {
self.register(status, Target::Modifier(Box::new(modifier)))
}
}
impl iron::middleware::AfterMiddleware for ErrorRouter {
fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
match (res.body.is_some(), res.status.and_then(|s| self.by_status.get(&s))) {
(false, Some(x)) => x.after(req, res),
_ => Ok(res)
}
}
fn catch(&self, req: &mut Request, err: IronError) -> IronResult<Response> {
match err.response.status.and_then(|s| self.by_status.get(&s)) {
Some(x) => x.catch(req, err),
None => Err(err)
}
}
}