1extern crate iron;
4
5use iron::prelude::*;
6use iron::modifier::Modifier;
7
8use std::collections::HashMap;
9use std::collections::hash_map;
10
11trait ModifierInner: Send + Sync {
12 fn clone_box(&self) -> Box<ModifierInner>;
13 fn apply_modify(self: Box<Self>, res: &mut Response);
14}
15
16impl<M: Modifier<Response> + Send + Sync + Clone + 'static> ModifierInner for M {
17 fn clone_box(&self) -> Box<ModifierInner> {
18 Box::new(self.clone())
19 }
20
21 fn apply_modify(self: Box<Self>, res: &mut Response) { self.modify(res) }
22}
23
24impl Modifier<Response> for Box<ModifierInner> {
25 fn modify(self, res: &mut Response) { self.apply_modify(res) }
26}
27
28enum Target {
29 AfterMiddleware(Box<iron::middleware::AfterMiddleware>),
30 Modifier(Box<ModifierInner>),
31 Handler(Box<iron::Handler>),
32}
33
34impl iron::middleware::AfterMiddleware for Target {
35 fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
36 match *self {
37 Target::AfterMiddleware(ref x) => x.after(req, res),
38 Target::Modifier(ref x) => Ok(res.set(x.clone_box())),
39 Target::Handler(ref x) => x.handle(req)
40 }
41 }
42
43 fn catch(&self, req: &mut Request, mut err: IronError) -> IronResult<Response> {
44 match *self {
45 Target::AfterMiddleware(ref x) => x.catch(req, err),
46 Target::Modifier(ref x) => { err.response.set_mut(x.clone_box()); Err(err) },
47 Target::Handler(ref x) => x.handle(req)
48 }
49 }
50}
51
52pub struct ErrorRouter {
53 by_status: HashMap<iron::status::Status, Target>
54}
55
56impl Default for ErrorRouter {
57 fn default() -> ErrorRouter { ErrorRouter { by_status: HashMap::new() } }
58}
59
60impl ErrorRouter {
61 pub fn new() -> Self { ErrorRouter::default() }
62
63 fn register(&mut self, status: iron::status::Status, target: Target) {
64 match self.by_status.entry(status) {
65 hash_map::Entry::Occupied(_) => panic!("Target for {:?} already registered.", status),
66 hash_map::Entry::Vacant(x) => x.insert(target)
67 };
68 }
69
70 pub fn handle_status<T: iron::Handler>(&mut self, status: iron::status::Status, handler: T) {
71 self.register(status, Target::Handler(Box::new(handler)))
72 }
73
74 pub fn after_status<T: iron::middleware::AfterMiddleware>
75 (&mut self, status: iron::status::Status, middleware: T) {
76 self.register(status, Target::AfterMiddleware(Box::new(middleware)))
77 }
78
79 pub fn modifier_for_status<T: Modifier<Response> + Send + Sync + Clone + 'static>
80 (&mut self, status: iron::status::Status, modifier: T) {
81 self.register(status, Target::Modifier(Box::new(modifier)))
82 }
83}
84
85impl iron::middleware::AfterMiddleware for ErrorRouter {
86 fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
87 match (res.body.is_some(), res.status.and_then(|s| self.by_status.get(&s))) {
88 (false, Some(x)) => x.after(req, res),
89 _ => Ok(res)
90 }
91 }
92
93 fn catch(&self, req: &mut Request, err: IronError) -> IronResult<Response> {
94 match err.response.status.and_then(|s| self.by_status.get(&s)) {
95 Some(x) => x.catch(req, err),
96 None => Err(err)
97 }
98 }
99}