Created
August 21, 2014 22:44
-
-
Save reem/f04c7b8f457d56b57c50 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![license = "MIT"] | |
extern crate error; | |
use std::sync::Arc; | |
use error::Error; | |
pub type IronResult<T> = Result<T, Box<Error>>; | |
pub struct Request; | |
pub struct Response; | |
#[deriving(Clone)] | |
struct IronListener { | |
handler: Arc<Box<Handler + Send + Sync>> | |
} | |
pub trait Handler: Send + Sync { | |
fn call(&self, &mut Request) -> IronResult<Response>; | |
fn catch(&self, &mut Request, Box<Error>) -> (Response, IronResult<()>); | |
} | |
impl Handler for fn(&mut Request) -> IronResult<Response> { | |
fn call(&self, req: &mut Request) -> IronResult<Response> { | |
self.call(req) | |
} | |
fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) { | |
(Response, Err(err)) | |
} | |
} | |
pub trait BeforeMiddleware: Send + Sync { | |
fn before(&self, &mut Request) -> IronResult<()>; | |
fn catch(&self, &mut Request, Box<Error>) -> IronResult<()>; | |
} | |
pub trait AfterMiddleware: Send + Sync { | |
fn after(&self, &mut Request, &mut Response) -> IronResult<()>; | |
// This response was generated by the `catch` function of Handlers and is abnormal in some way. | |
fn catch(&self, &mut Request, &mut Response, Box<Error>) -> IronResult<()>; | |
} | |
pub trait AroundMiddleware: Handler { | |
fn with_handler(&mut self, handler: Box<Handler + Send + Sync>); | |
} | |
pub trait Chain: Send + Sync { | |
fn dispatch(&self, &mut Request) -> IronResult<Response>; | |
fn new<H: Handler>(H) -> Self; | |
fn catch(&self, &mut Request, Box<Error>) -> (Response, IronResult<()>); | |
} | |
pub struct StackChain { | |
befores: Vec<Box<BeforeMiddleware + Send + Sync>>, | |
afters: Vec<Box<AfterMiddleware + Send + Sync>>, | |
handler: Box<Handler + Send + Sync> | |
} | |
impl Chain for StackChain { | |
fn new<H: Handler>(handler: H) -> StackChain { | |
StackChain { | |
befores: vec![], | |
afters: vec![], | |
handler: box handler as Box<Handler + Send + Sync> | |
} | |
} | |
fn dispatch(&self, req: &mut Request) -> IronResult<Response> { | |
let before_result = run_befores(req, self.befores.as_slice(), None); | |
let (res, err) = match before_result { | |
Ok(()) => match self.handler.call(req) { | |
Ok(res) => (res, None), | |
Err(e) => run_handler_catch(req, e, &self.handler) | |
}, | |
Err(e) => run_handler_catch(req, e, &self.handler) | |
}; | |
run_afters(req, res, err, self.afters.as_slice()) | |
} | |
fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) { | |
let before_result = run_befores(req, self.befores.as_slice(), Some(err)); | |
let (res, err) = match before_result { | |
Ok(()) => match self.handler.call(req) { | |
Ok(res) => (res, None), | |
Err(e) => run_handler_catch(req, e, &self.handler) | |
}, | |
Err(e) => run_handler_catch(req, e, &self.handler) | |
}; | |
match run_afters(req, res, err, self.afters.as_slice()) { | |
Ok(res) => (res, Ok(())), | |
Err(err) => (Response, Err(err)) | |
} | |
} | |
} | |
fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error>>) -> IronResult<()> { | |
match err { | |
Some(mut e) => { | |
for (i, before) in befores.iter().enumerate() { | |
match before.catch(req, e) { | |
Ok(_) => return run_befores(req, befores, None), | |
Err(new) => e = new | |
} | |
} | |
Err(e) | |
}, | |
None => { | |
for (i, before) in befores.iter().enumerate() { | |
match before.before(req) { | |
Ok(_) => (), | |
Err(err) => return run_befores(req, befores.slice_from(i), Some(err)) | |
} | |
} | |
Ok(()) | |
} | |
} | |
} | |
fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error>>, | |
afters: &[Box<AfterMiddleware>]) -> IronResult<Response> { | |
match err { | |
Some(mut e) => { | |
for (i, after) in afters.iter().enumerate() { | |
match after.catch(req, &mut res, e) { | |
Ok(_) => return run_afters(req, res, None, afters), | |
Err(new) => e = new | |
} | |
} | |
Err(e) | |
}, | |
None => { | |
for (i, after) in afters.iter().enumerate() { | |
match after.after(req, &mut res) { | |
Ok(_) => (), | |
Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i)) | |
} | |
} | |
Ok(res) | |
} | |
} | |
} | |
fn run_handler_catch(req: &mut Request, err: Box<Error>, | |
handler: &Box<Handler>) -> (Response, Option<Box<Error>>) { | |
match handler.catch(req, err) { | |
(res, Ok(())) => (res, None), | |
(res, Err(e)) => (res, Some(e)) | |
} | |
} | |
impl Handler for Box<Chain + Send + Sync> { | |
fn call(&self, req: &mut Request) -> IronResult<Response> { | |
self.dispatch(req) | |
} | |
fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) { | |
self.catch(req, err) | |
} | |
} | |
impl Handler for Arc<Box<Chain + Send + Sync>> { | |
fn call(&self, req: &mut Request) -> IronResult<Response> { | |
self.dispatch(req) | |
} | |
fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) { | |
self.catch(req, err) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment