From 45ecb87eab5fc4b8ff7a348e82444e96ea991a6f Mon Sep 17 00:00:00 2001
From: Nikolay Kim <fafhrd91@gmail.com>
Date: Sat, 25 Nov 2017 10:24:45 -0800
Subject: [PATCH] allow middlware error result

---
 src/middlewares/mod.rs     | 12 ++++++++----
 src/middlewares/session.rs | 10 +++++-----
 src/pipeline.rs            | 16 +++++++++++-----
 src/task.rs                | 20 ++++++++++++--------
 tests/test_server.rs       |  2 +-
 5 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/src/middlewares/mod.rs b/src/middlewares/mod.rs
index 619e3570..6699edab 100644
--- a/src/middlewares/mod.rs
+++ b/src/middlewares/mod.rs
@@ -13,6 +13,8 @@ pub use self::session::{RequestSession, Session, SessionImpl,
 
 /// Middleware start result
 pub enum Started {
+    /// Moddleware error
+    Err(Error),
     /// Execution completed
     Done(HttpRequest),
     /// New http response got generated. If middleware generates response
@@ -24,8 +26,10 @@ pub enum Started {
 
 /// Middleware execution result
 pub enum Response {
+    /// Moddleware error
+    Err(Error),
     /// New http response got generated
-    Response(HttpResponse),
+    Done(HttpResponse),
     /// Result is a future that resolves to a new http response
     Future(Box<Future<Item=HttpResponse, Error=Error>>),
 }
@@ -49,12 +53,12 @@ pub trait Middleware {
     }
 
     /// Method is called when handler returns response,
-    /// but before sending body stream to peer.
+    /// but before sending http message to peer.
     fn response(&self, req: &mut HttpRequest, resp: HttpResponse) -> Response {
-        Response::Response(resp)
+        Response::Done(resp)
     }
 
-    /// Method is called after http response get sent to peer.
+    /// Method is called after body stream get sent to peer.
     fn finish(&self, req: &mut HttpRequest, resp: &HttpResponse) -> Finished {
         Finished::Done
     }
diff --git a/src/middlewares/session.rs b/src/middlewares/session.rs
index 89153878..79f70804 100644
--- a/src/middlewares/session.rs
+++ b/src/middlewares/session.rs
@@ -106,7 +106,7 @@ impl<T: SessionBackend> Middleware for SessionStorage<T> {
         if let Some(s_box) = req.extensions().remove::<Arc<SessionImplBox>>() {
             s_box.0.write(resp)
         } else {
-            Response::Response(resp)
+            Response::Done(resp)
         }
     }
 }
@@ -151,7 +151,7 @@ impl SessionImpl for DummySessionImpl {
     fn remove(&mut self, key: &str) {}
     fn clear(&mut self) {}
     fn write(&self, resp: HttpResponse) -> Response {
-        Response::Response(resp)
+        Response::Done(resp)
     }
 }
 
@@ -176,7 +176,7 @@ impl SessionImpl for CookieSession {
     }
 
     fn clear(&mut self) {
-        let cookies: Vec<_> = self.jar.iter().map(|c| c.clone()).collect();
+        let cookies: Vec<_> = self.jar.iter().cloned().collect();
         for cookie in cookies {
             self.jar.remove(cookie);
         }
@@ -185,11 +185,11 @@ impl SessionImpl for CookieSession {
     fn write(&self, mut resp: HttpResponse) -> Response {
         for cookie in self.jar.delta() {
             match HeaderValue::from_str(&cookie.to_string()) {
-                Err(err) => return Response::Response(err.error_response()),
+                Err(err) => return Response::Err(err.into()),
                 Ok(val) => resp.headers.append(header::SET_COOKIE, val),
             };
         }
-        Response::Response(resp)
+        Response::Done(resp)
     }
 }
 
diff --git a/src/pipeline.rs b/src/pipeline.rs
index 9345459b..367f90eb 100644
--- a/src/pipeline.rs
+++ b/src/pipeline.rs
@@ -309,6 +309,7 @@ impl Start {
                             Err(err) => return Err(err)
                         }
                     },
+                    Started::Err(err) => return Err(err),
                 }
             }
         }
@@ -348,6 +349,7 @@ impl Start {
                                     self.fut = Some(fut);
                                     continue 'outer
                                 },
+                                Started::Err(err) => return Err(err),
                             }
                         }
                     }
@@ -375,13 +377,15 @@ impl MiddlewaresResponse {
     }
 
     pub fn response(&mut self, req: &mut HttpRequest, mut resp: HttpResponse)
-                    -> Option<HttpResponse>
+                    -> Result<Option<HttpResponse>, Error>
     {
         loop {
             resp = match self.middlewares[self.idx].response(req, resp) {
-                Response::Response(r) => {
+                Response::Err(err) =>
+                    return Err(err),
+                Response::Done(r) => {
                     if self.idx == 0 {
-                        return Some(r)
+                        return Ok(Some(r))
                     } else {
                         self.idx -= 1;
                         r
@@ -389,7 +393,7 @@ impl MiddlewaresResponse {
                 },
                 Response::Future(fut) => {
                     self.fut = Some(fut);
-                    return None
+                    return Ok(None)
                 },
             };
         }
@@ -417,7 +421,9 @@ impl MiddlewaresResponse {
                     return Ok(Async::Ready(Some(resp)))
                 } else {
                     match self.middlewares[self.idx].response(req, resp) {
-                        Response::Response(r) => {
+                        Response::Err(err) =>
+                            return Err(err),
+                        Response::Done(r) => {
                             self.idx -= 1;
                             resp = r
                         },
diff --git a/src/task.rs b/src/task.rs
index 6e12460b..a74389c0 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -218,14 +218,18 @@ impl Task {
                         Frame::Message(mut resp) => {
                             // run middlewares
                             if let Some(mut middlewares) = self.middlewares.take() {
-                                if let Some(mut resp) = middlewares.response(req, resp) {
-                                    let result = io.start(req, &mut resp)?;
-                                    self.prepared = Some(resp);
-                                    result
-                                } else {
-                                    // middlewares need to run some futures
-                                    self.middlewares = Some(middlewares);
-                                    return self.poll_io(io, req)
+                                match middlewares.response(req, resp) {
+                                    Ok(Some(mut resp)) => {
+                                        let result = io.start(req, &mut resp)?;
+                                        self.prepared = Some(resp);
+                                        result
+                                    }
+                                    Ok(None) => {
+                                        // middlewares need to run some futures
+                                        self.middlewares = Some(middlewares);
+                                        return self.poll_io(io, req)
+                                    }
+                                    Err(err) => return Err(err),
                                 }
                             } else {
                                 let result = io.start(req, &mut resp)?;
diff --git a/tests/test_server.rs b/tests/test_server.rs
index d3e9d035..efc963ff 100644
--- a/tests/test_server.rs
+++ b/tests/test_server.rs
@@ -68,7 +68,7 @@ impl middlewares::Middleware for MiddlewareTest {
 
     fn response(&self, _: &mut HttpRequest, resp: HttpResponse) -> middlewares::Response {
         self.response.store(self.response.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
-        middlewares::Response::Response(resp)
+        middlewares::Response::Done(resp)
     }
 
     fn finish(&self, _: &mut HttpRequest, _: &HttpResponse) -> middlewares::Finished {