use std::sync::Arc;
use {Request, Response, FerrumResult, FerrumError};
pub trait Handler: Send + Sync + 'static {
fn handle(&self, request: &mut Request) -> FerrumResult<Response>;
}
pub trait BeforeMiddleware: Send + Sync + 'static {
fn before(&self, _request: &mut Request) -> FerrumResult<()> {
Ok(())
}
fn catch(&self, _request: &mut Request, error: FerrumError) -> FerrumResult<()> {
Err(error)
}
}
pub trait AfterMiddleware: Send + Sync + 'static {
fn after(&self, _request: &mut Request, response: Response) -> FerrumResult<Response> {
Ok(response)
}
fn catch(&self, _request: &mut Request, error: FerrumError) -> FerrumResult<Response> {
Err(error)
}
}
pub trait AroundMiddleware {
fn around(self, handler: Box<Handler>) -> Box<Handler>;
}
pub struct Chain {
befores: Vec<Box<BeforeMiddleware>>,
afters: Vec<Box<AfterMiddleware>>,
handler: Option<Box<Handler>>
}
impl Chain {
pub fn new<H: Handler>(handler: H) -> Chain {
Chain {
befores: vec![],
afters: vec![],
handler: Some(Box::new(handler) as Box<Handler>)
}
}
pub fn link<B, A>(&mut self, link: (B, A)) -> &mut Chain
where A: AfterMiddleware, B: BeforeMiddleware
{
let (before, after) = link;
self.befores.push(Box::new(before) as Box<BeforeMiddleware>);
self.afters.push(Box::new(after) as Box<AfterMiddleware>);
self
}
pub fn link_before<B>(&mut self, before: B) -> &mut Chain
where B: BeforeMiddleware
{
self.befores.push(Box::new(before) as Box<BeforeMiddleware>);
self
}
pub fn link_after<A>(&mut self, after: A) -> &mut Chain
where A: AfterMiddleware
{
self.afters.push(Box::new(after) as Box<AfterMiddleware>);
self
}
pub fn around<A>(&mut self, around: A) -> &mut Chain
where A: AroundMiddleware
{
self.link_around(around)
}
pub fn link_around<A>(&mut self, around: A) -> &mut Chain
where A: AroundMiddleware
{
let mut handler = self.handler.take().unwrap();
handler = around.around(handler);
self.handler = Some(handler);
self
}
}
impl Handler for Chain {
fn handle(&self, req: &mut Request) -> FerrumResult<Response> {
self.continue_from_before(req, 0)
}
}
impl Chain {
fn fail_from_before(&self, req: &mut Request, index: usize,
mut err: FerrumError) -> FerrumResult<Response> {
if index >= self.befores.len() {
return self.fail_from_handler(req, err)
}
for (i, before) in self.befores[index..].iter().enumerate() {
err = match before.catch(req, err) {
Err(err) => err,
Ok(()) => return self.continue_from_before(req, index + i + 1)
};
}
self.fail_from_handler(req, err)
}
fn fail_from_handler(&self, req: &mut Request,
err: FerrumError) -> FerrumResult<Response> {
self.fail_from_after(req, 0, err)
}
fn fail_from_after(&self, req: &mut Request, index: usize,
mut err: FerrumError) -> FerrumResult<Response> {
if index == self.afters.len() { return Err(err) }
for (i, after) in self.afters[index..].iter().enumerate() {
err = match after.catch(req, err) {
Err(err) => err,
Ok(res) => return self.continue_from_after(req, index + i + 1, res)
}
}
Err(err)
}
fn continue_from_before(&self, req: &mut Request,
index: usize) -> FerrumResult<Response> {
if index >= self.befores.len() {
return self.continue_from_handler(req)
}
for (i, before) in self.befores[index..].iter().enumerate() {
match before.before(req) {
Ok(()) => {},
Err(err) => return self.fail_from_before(req, index + i + 1, err)
}
}
self.continue_from_handler(req)
}
fn continue_from_handler(&self, req: &mut Request) -> FerrumResult<Response> {
match self.handler.as_ref().unwrap().handle(req) {
Ok(res) => self.continue_from_after(req, 0, res),
Err(err) => self.fail_from_handler(req, err)
}
}
fn continue_from_after(&self, req: &mut Request, index: usize,
mut res: Response) -> FerrumResult<Response> {
if index >= self.afters.len() {
return Ok(res);
}
for (i, after) in self.afters[index..].iter().enumerate() {
res = match after.after(req, res) {
Ok(r) => r,
Err(err) => return self.fail_from_after(req, index + i + 1, err)
}
}
Ok(res)
}
}
impl<F> Handler for F
where F: Send + Sync + 'static + Fn(&mut Request) -> FerrumResult<Response>
{
fn handle(&self, req: &mut Request) -> FerrumResult<Response> {
(*self)(req)
}
}
impl Handler for Box<Handler> {
fn handle(&self, req: &mut Request) -> FerrumResult<Response> {
(**self).handle(req)
}
}
impl<F> BeforeMiddleware for F
where F: Send + Sync + 'static + Fn(&mut Request) -> FerrumResult<()>
{
fn before(&self, req: &mut Request) -> FerrumResult<()> {
(*self)(req)
}
}
impl BeforeMiddleware for Box<BeforeMiddleware> {
fn before(&self, req: &mut Request) -> FerrumResult<()> {
(**self).before(req)
}
fn catch(&self, req: &mut Request, err: FerrumError) -> FerrumResult<()> {
(**self).catch(req, err)
}
}
impl<T> BeforeMiddleware for Arc<T>
where T: BeforeMiddleware
{
fn before(&self, req: &mut Request) -> FerrumResult<()> {
(**self).before(req)
}
fn catch(&self, req: &mut Request, err: FerrumError) -> FerrumResult<()> {
(**self).catch(req, err)
}
}
impl<F> AfterMiddleware for F
where F: Send + Sync + 'static + Fn(&mut Request, Response) -> FerrumResult<Response>
{
fn after(&self, req: &mut Request, res: Response) -> FerrumResult<Response> {
(*self)(req, res)
}
}
impl AfterMiddleware for Box<AfterMiddleware> {
fn after(&self, req: &mut Request, res: Response) -> FerrumResult<Response> {
(**self).after(req, res)
}
fn catch(&self, req: &mut Request, err: FerrumError) -> FerrumResult<Response> {
(**self).catch(req, err)
}
}
impl<T> AfterMiddleware for Arc<T> where T: AfterMiddleware {
fn after(&self, req: &mut Request, res: Response) -> FerrumResult<Response> {
(**self).after(req, res)
}
fn catch(&self, req: &mut Request, err: FerrumError) -> FerrumResult<Response> {
(**self).catch(req, err)
}
}
impl<F> AroundMiddleware for F
where F: FnOnce(Box<Handler>) -> Box<Handler>
{
fn around(self, handler: Box<Handler>) -> Box<Handler> {
self(handler)
}
}
#[cfg(test)]
mod test;