From ebf96f3f5fd5c192f5c3cb4e331f732970301c2b Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Thu, 16 Feb 2017 14:09:41 -0800 Subject: [PATCH] fix(http): send errors as frame errors Additionally, only close read side, so it's potentially possible to write a response for an error. --- src/http/conn.rs | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/http/conn.rs b/src/http/conn.rs index 3e2b80ce..b291a013 100644 --- a/src/http/conn.rs +++ b/src/http/conn.rs @@ -83,25 +83,20 @@ impl Conn { Ok(Some(head)) => (head.version, head), Ok(None) => return Ok(Async::NotReady), Err(e) => { - let must_respond_with_error = !self.state.was_idle(); - self.state.close(); + self.state.close_read(); self.io.consume_leading_lines(); - let ret = if !self.io.read_buf().is_empty() { - error!("parse error ({}) with bytes: {:?}", e, self.io.read_buf()); + let was_mid_parse = !self.io.read_buf().is_empty(); + let must_respond_with_error = !self.state.was_idle(); + return if was_mid_parse { + debug!("parse error ({}) with bytes: {:?}", e, self.io.read_buf()); + Ok(Async::Ready(Some(Frame::Error { error: e }))) + } else if must_respond_with_error { + trace!("parse error with 0 input, err = {:?}", e); Ok(Async::Ready(Some(Frame::Error { error: e }))) } else { - trace!("parse error with 0 input, err = {:?}", e); - if must_respond_with_error { - match e { - ::Error::Io(io) => Err(io), - other => Err(io::Error::new(io::ErrorKind::UnexpectedEof, other)), - } - } else { - debug!("socket complete"); - Ok(Async::Ready(None)) - } + debug!("socket complete"); + Ok(Async::Ready(None)) }; - return ret; } }; @@ -111,7 +106,7 @@ impl Conn { Ok(d) => d, Err(e) => { error!("decoder error = {:?}", e); - self.state.close(); + self.state.close_read(); return Ok(Async::Ready(Some(Frame::Error { error: e }))); } }; @@ -128,7 +123,7 @@ impl Conn { }, _ => { error!("unimplemented HTTP Version = {:?}", version); - self.state.close(); + self.state.close_read(); return Ok(Async::Ready(Some(Frame::Error { error: ::Error::Version }))); } } @@ -310,6 +305,10 @@ where I: Io, .map(|async| async.map(|chunk| Some(Frame::Body { chunk: chunk }))) + .or_else(|err| { + self.state.close_read(); + Ok(Async::Ready(Some(Frame::Error { error: err.into() }))) + }) } else { trace!("poll when on keep-alive"); Ok(Async::NotReady) @@ -476,6 +475,12 @@ impl State { self.keep_alive.disable(); } + fn close_read(&mut self) { + trace!("State::close_read()"); + self.reading = Reading::Closed; + self.keep_alive.disable(); + } + fn try_keep_alive(&mut self) { match (&self.reading, &self.writing) { (&Reading::KeepAlive, &Writing::KeepAlive) => {