From f4972150cc141b4a5146d9001f44966e0620e7cd Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 25 Nov 2017 09:40:57 -0800 Subject: [PATCH] better middleware error handling --- src/middlewares/mod.rs | 4 +-- src/pipeline.rs | 73 ++++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 41 deletions(-) diff --git a/src/middlewares/mod.rs b/src/middlewares/mod.rs index 6a0ea3c9f..3cb37e3b9 100644 --- a/src/middlewares/mod.rs +++ b/src/middlewares/mod.rs @@ -16,7 +16,7 @@ pub enum Started { /// handler execution halts. Response(HttpRequest, HttpResponse), /// Execution completed, runs future to completion. - Future(Box), Error=(HttpRequest, HttpResponse)>>), + Future(Box), Error=Error>>), } /// Middleware execution result @@ -24,7 +24,7 @@ pub enum Response { /// New http response got generated Response(HttpResponse), /// Result is a future that resolves to a new http response - Future(Box>), + Future(Box>), } /// Middleware finish result diff --git a/src/pipeline.rs b/src/pipeline.rs index 6152ac15e..a243b5238 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -34,12 +34,13 @@ impl Pipeline { Pipeline(PipelineState::Task(Box::new((task, req)))) } else { match Start::init(mw, req, handler, payload) { - StartResult::Ready(res) => { - Pipeline(PipelineState::Handle(res)) - }, - StartResult::NotReady(res) => { - Pipeline(PipelineState::Starting(res)) - }, + Ok(StartResult::Ready(res)) => + Pipeline(PipelineState::Handle(res)), + Ok(StartResult::NotReady(res)) => + Pipeline(PipelineState::Starting(res)), + Err(err) => + Pipeline(PipelineState::Error( + Box::new((Task::reply(err), HttpRequest::for_error())))) } } } @@ -70,12 +71,15 @@ impl Pipeline { } PipelineState::Starting(mut st) => { match st.poll() { - Async::NotReady => { + Ok(Async::NotReady) => { self.0 = PipelineState::Starting(st); return Ok(Async::NotReady) } - Async::Ready(h) => + Ok(Async::Ready(h)) => self.0 = PipelineState::Handle(h), + Err(err) => + self.0 = PipelineState::Error( + Box::new((Task::reply(err), HttpRequest::for_error()))) } } PipelineState::Handle(mut st) => { @@ -222,7 +226,7 @@ impl Finish { } } -type Fut = Box), Error=(HttpRequest, HttpResponse)>>; +type Fut = Box), Error=Error>>; /// Middlewares start executor struct Start { @@ -242,8 +246,9 @@ enum StartResult { impl Start { fn init(mw: Rc>>, - req: HttpRequest, handler: PipelineHandler, payload: Payload) -> StartResult - { + req: HttpRequest, + handler: PipelineHandler, + payload: Payload) -> Result { Start { idx: 0, fut: None, @@ -266,13 +271,13 @@ impl Start { task } - fn start(mut self, mut req: HttpRequest) -> StartResult { + fn start(mut self, mut req: HttpRequest) -> Result { loop { if self.idx >= self.middlewares.len() { let task = (unsafe{&*self.hnd})( &mut req, self.payload.take().expect("Something is completlywrong")); - return StartResult::Ready( - Box::new(Handle::new(self.idx-1, req, self.prepare(task), self.middlewares))) + return Ok(StartResult::Ready( + Box::new(Handle::new(self.idx-1, req, self.prepare(task), self.middlewares)))) } else { req = match self.middlewares[self.idx].start(req) { Started::Done(req) => { @@ -280,31 +285,27 @@ impl Start { req } Started::Response(req, resp) => { - return StartResult::Ready( + return Ok(StartResult::Ready( Box::new(Handle::new( - self.idx, req, self.prepare(Task::reply(resp)), self.middlewares))) + self.idx, req, self.prepare(Task::reply(resp)), self.middlewares)))) }, Started::Future(mut fut) => { match fut.poll() { Ok(Async::NotReady) => { self.fut = Some(fut); - return StartResult::NotReady(self) + return Ok(StartResult::NotReady(self)) } Ok(Async::Ready((req, resp))) => { self.idx += 1; if let Some(resp) = resp { - return StartResult::Ready( + return Ok(StartResult::Ready( Box::new(Handle::new( self.idx, req, - self.prepare(Task::reply(resp)), self.middlewares))) + self.prepare(Task::reply(resp)), self.middlewares)))) } req } - Err((req, resp)) => { - return StartResult::Ready(Box::new(Handle::new( - self.idx, req, - self.prepare(Task::reply(resp)), self.middlewares))) - } + Err(err) => return Err(err) } }, } @@ -312,23 +313,23 @@ impl Start { } } - fn poll(&mut self) -> Async> { + fn poll(&mut self) -> Poll, Error> { 'outer: loop { match self.fut.as_mut().unwrap().poll() { - Ok(Async::NotReady) => return Async::NotReady, + Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready((mut req, resp))) => { self.idx += 1; if let Some(resp) = resp { - return Async::Ready(Box::new(Handle::new( + return Ok(Async::Ready(Box::new(Handle::new( self.idx, req, - self.prepare(Task::reply(resp)), Rc::clone(&self.middlewares)))) + self.prepare(Task::reply(resp)), Rc::clone(&self.middlewares))))) } if self.idx >= self.middlewares.len() { let task = (unsafe{&*self.hnd})( &mut req, self.payload.take().expect("Something is completlywrong")); - return Async::Ready(Box::new(Handle::new( + return Ok(Async::Ready(Box::new(Handle::new( self.idx-1, req, - self.prepare(task), Rc::clone(&self.middlewares)))) + self.prepare(task), Rc::clone(&self.middlewares))))) } else { loop { req = match self.middlewares[self.idx].start(req) { @@ -337,10 +338,10 @@ impl Start { req } Started::Response(req, resp) => { - return Async::Ready(Box::new(Handle::new( + return Ok(Async::Ready(Box::new(Handle::new( self.idx, req, self.prepare(Task::reply(resp)), - Rc::clone(&self.middlewares)))) + Rc::clone(&self.middlewares))))) }, Started::Future(mut fut) => { self.fut = Some(fut); @@ -350,18 +351,12 @@ impl Start { } } } - Err((req, resp)) => { - return Async::Ready(Box::new(Handle::new( - self.idx, req, - self.prepare(Task::reply(resp)), - Rc::clone(&self.middlewares)))) - } + Err(err) => return Err(err) } } } } - /// Middlewares response executor pub(crate) struct MiddlewaresResponse { idx: usize,