Skip to content

Instantly share code, notes, and snippets.

@reem
Created August 21, 2014 22:44
Show Gist options
  • Save reem/f04c7b8f457d56b57c50 to your computer and use it in GitHub Desktop.
Save reem/f04c7b8f457d56b57c50 to your computer and use it in GitHub Desktop.
#![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