mirror of
https://github.com/fafhrd91/actix-web
synced 2025-01-18 13:51:50 +01:00
better pipeline error handling
This commit is contained in:
parent
64ade803f9
commit
1fc64bc83d
12
src/h1.rs
12
src/h1.rs
@ -106,8 +106,7 @@ impl<T, H> Http1<T, H>
|
||||
}
|
||||
|
||||
// this is anoying
|
||||
match item.task.poll_io(&mut self.stream)
|
||||
{
|
||||
match item.task.poll_io(&mut self.stream) {
|
||||
Ok(Async::Ready(ready)) => {
|
||||
not_ready = false;
|
||||
|
||||
@ -126,9 +125,10 @@ impl<T, H> Http1<T, H>
|
||||
// no more IO for this iteration
|
||||
io = true;
|
||||
},
|
||||
Err(_) => {
|
||||
Err(err) => {
|
||||
// it is not possible to recover from error
|
||||
// during task handling, so just drop connection
|
||||
error!("Unhandled error: {}", err);
|
||||
return Err(())
|
||||
}
|
||||
}
|
||||
@ -139,8 +139,10 @@ impl<T, H> Http1<T, H>
|
||||
not_ready = false;
|
||||
item.finished = true;
|
||||
},
|
||||
Err(_) =>
|
||||
item.error = true,
|
||||
Err(err) => {
|
||||
item.error = true;
|
||||
error!("Unhandled error: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
idx += 1;
|
||||
|
@ -92,7 +92,8 @@ impl<T, H> Http2<T, H>
|
||||
not_ready = false;
|
||||
},
|
||||
Ok(Async::NotReady) => (),
|
||||
Err(_) => {
|
||||
Err(err) => {
|
||||
error!("Unhandled error: {}", err);
|
||||
item.eof = true;
|
||||
item.error = true;
|
||||
item.stream.reset(Reason::INTERNAL_ERROR);
|
||||
@ -105,9 +106,10 @@ impl<T, H> Http2<T, H>
|
||||
not_ready = false;
|
||||
item.finished = true;
|
||||
},
|
||||
Err(_) => {
|
||||
Err(err) => {
|
||||
item.error = true;
|
||||
item.finished = true;
|
||||
error!("Unhandled error: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ impl Pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn poll_io<T: Writer>(&mut self, io: &mut T) -> Poll<bool, ()> {
|
||||
pub(crate) fn poll_io<T: Writer>(&mut self, io: &mut T) -> Poll<bool, Error> {
|
||||
loop {
|
||||
let state = mem::replace(&mut self.0, PipelineState::None);
|
||||
match state {
|
||||
@ -161,7 +161,7 @@ impl Handle {
|
||||
idx: idx, req: req, task:task, middlewares: mw }
|
||||
}
|
||||
|
||||
fn poll_io<T: Writer>(&mut self, io: &mut T) -> Poll<bool, ()> {
|
||||
fn poll_io<T: Writer>(&mut self, io: &mut T) -> Poll<bool, Error> {
|
||||
self.task.poll_io(io, &mut self.req)
|
||||
}
|
||||
|
||||
@ -262,8 +262,7 @@ impl Start {
|
||||
if self.disconnected {
|
||||
task.disconnected()
|
||||
}
|
||||
task.set_middlewares(
|
||||
MiddlewaresResponse::new(self.idx, Rc::clone(&self.middlewares)));
|
||||
task.set_middlewares(MiddlewaresResponse::new(Rc::clone(&self.middlewares)));
|
||||
task
|
||||
}
|
||||
|
||||
@ -366,16 +365,15 @@ impl Start {
|
||||
/// Middlewares response executor
|
||||
pub(crate) struct MiddlewaresResponse {
|
||||
idx: usize,
|
||||
fut: Option<Box<Future<Item=HttpResponse, Error=HttpResponse>>>,
|
||||
fut: Option<Box<Future<Item=HttpResponse, Error=Error>>>,
|
||||
middlewares: Rc<Vec<Box<Middleware>>>,
|
||||
}
|
||||
|
||||
impl MiddlewaresResponse {
|
||||
|
||||
fn new(idx: usize, mw: Rc<Vec<Box<Middleware>>>) -> MiddlewaresResponse {
|
||||
let idx = if idx == 0 { 0 } else { idx - 1 };
|
||||
fn new(mw: Rc<Vec<Box<Middleware>>>) -> MiddlewaresResponse {
|
||||
MiddlewaresResponse {
|
||||
idx: idx,
|
||||
idx: 0,
|
||||
fut: None,
|
||||
middlewares: mw }
|
||||
}
|
||||
@ -401,7 +399,7 @@ impl MiddlewaresResponse {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll(&mut self, req: &mut HttpRequest) -> Poll<Option<HttpResponse>, ()> {
|
||||
pub fn poll(&mut self, req: &mut HttpRequest) -> Poll<Option<HttpResponse>, Error> {
|
||||
if self.fut.is_none() {
|
||||
return Ok(Async::Ready(None))
|
||||
}
|
||||
@ -409,11 +407,13 @@ impl MiddlewaresResponse {
|
||||
loop {
|
||||
// poll latest fut
|
||||
let mut resp = match self.fut.as_mut().unwrap().poll() {
|
||||
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
||||
Ok(Async::Ready(resp)) | Err(resp) => {
|
||||
Ok(Async::NotReady) =>
|
||||
return Ok(Async::NotReady),
|
||||
Ok(Async::Ready(resp)) => {
|
||||
self.idx += 1;
|
||||
resp
|
||||
}
|
||||
Err(err) => return Err(err)
|
||||
};
|
||||
|
||||
loop {
|
||||
|
42
src/task.rs
42
src/task.rs
@ -170,7 +170,7 @@ impl Task {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn poll_io<T>(&mut self, io: &mut T, req: &mut HttpRequest) -> Poll<bool, ()>
|
||||
pub(crate) fn poll_io<T>(&mut self, io: &mut T, req: &mut HttpRequest) -> Poll<bool, Error>
|
||||
where T: Writer
|
||||
{
|
||||
trace!("POLL-IO frames:{:?}", self.frames.len());
|
||||
@ -181,35 +181,30 @@ impl Task {
|
||||
} else if self.drain.is_empty() {
|
||||
// poll stream
|
||||
if self.state == TaskRunningState::Running {
|
||||
match self.poll() {
|
||||
Ok(Async::Ready(_)) => {
|
||||
match self.poll()? {
|
||||
Async::Ready(_) => {
|
||||
self.state = TaskRunningState::Done;
|
||||
},
|
||||
Ok(Async::NotReady) => (),
|
||||
Err(_) => return Err(())
|
||||
Async::NotReady => (),
|
||||
}
|
||||
}
|
||||
|
||||
// process middlewares response
|
||||
if let Some(mut middlewares) = self.middlewares.take() {
|
||||
match middlewares.poll(req) {
|
||||
Err(_) => return Err(()),
|
||||
Ok(Async::NotReady) => {
|
||||
match middlewares.poll(req)? {
|
||||
Async::NotReady => {
|
||||
self.middlewares = Some(middlewares);
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
Ok(Async::Ready(None)) => {
|
||||
Async::Ready(None) => {
|
||||
self.middlewares = Some(middlewares);
|
||||
}
|
||||
Ok(Async::Ready(Some(mut response))) => {
|
||||
let result = io.start(req, &mut response);
|
||||
Async::Ready(Some(mut response)) => {
|
||||
let result = io.start(req, &mut response)?;
|
||||
self.prepared = Some(response);
|
||||
match result {
|
||||
Ok(WriterState::Pause) => {
|
||||
self.state.pause();
|
||||
}
|
||||
Ok(WriterState::Done) => self.state.resume(),
|
||||
Err(_) => return Err(())
|
||||
WriterState::Pause => self.state.pause(),
|
||||
WriterState::Done => self.state.resume(),
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -225,7 +220,7 @@ impl Task {
|
||||
// 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);
|
||||
let result = io.start(req, &mut resp)?;
|
||||
self.prepared = Some(resp);
|
||||
result
|
||||
} else {
|
||||
@ -234,17 +229,17 @@ impl Task {
|
||||
return self.poll_io(io, req)
|
||||
}
|
||||
} else {
|
||||
let result = io.start(req, &mut resp);
|
||||
let result = io.start(req, &mut resp)?;
|
||||
self.prepared = Some(resp);
|
||||
result
|
||||
}
|
||||
}
|
||||
Frame::Payload(Some(chunk)) => {
|
||||
io.write(chunk.as_ref())
|
||||
io.write(chunk.as_ref())?
|
||||
},
|
||||
Frame::Payload(None) => {
|
||||
self.iostate = TaskIOState::Done;
|
||||
io.write_eof()
|
||||
io.write_eof()?
|
||||
},
|
||||
Frame::Drain(fut) => {
|
||||
self.drain.push(fut);
|
||||
@ -253,12 +248,11 @@ impl Task {
|
||||
};
|
||||
|
||||
match res {
|
||||
Ok(WriterState::Pause) => {
|
||||
WriterState::Pause => {
|
||||
self.state.pause();
|
||||
break
|
||||
}
|
||||
Ok(WriterState::Done) => self.state.resume(),
|
||||
Err(_) => return Err(())
|
||||
WriterState::Done => self.state.resume(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -272,7 +266,7 @@ impl Task {
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("Error sending data: {}", err);
|
||||
return Err(())
|
||||
return Err(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user