1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-28 01:52:57 +01:00

simplify error handling

This commit is contained in:
Nikolay Kim 2018-10-07 00:04:38 -07:00
parent b0ca6220f0
commit 8d85c45c1d
4 changed files with 47 additions and 47 deletions

View File

@ -69,10 +69,10 @@ impl Body {
/// Is this binary body. /// Is this binary body.
#[inline] #[inline]
pub(crate) fn binary(self) -> Binary { pub(crate) fn into_binary(self) -> Option<Binary> {
match self { match self {
Body::Binary(b) => b, Body::Binary(b) => Some(b),
_ => panic!(), _ => None,
} }
} }
} }

View File

@ -374,7 +374,7 @@ impl ResponseError for cookie::ParseError {
#[derive(Debug)] #[derive(Debug)]
/// A set of errors that can occur during dispatching http requests /// A set of errors that can occur during dispatching http requests
pub enum DispatchError<E> { pub enum DispatchError<E: fmt::Display + fmt::Debug> {
/// Service error /// Service error
// #[fail(display = "Application specific error: {}", _0)] // #[fail(display = "Application specific error: {}", _0)]
Service(E), Service(E),
@ -413,13 +413,13 @@ pub enum DispatchError<E> {
Unknown, Unknown,
} }
impl<E> From<ParseError> for DispatchError<E> { impl<E: fmt::Display + fmt::Debug> From<ParseError> for DispatchError<E> {
fn from(err: ParseError) -> Self { fn from(err: ParseError) -> Self {
DispatchError::Parse(err) DispatchError::Parse(err)
} }
} }
impl<E> From<io::Error> for DispatchError<E> { impl<E: fmt::Display + fmt::Debug> From<io::Error> for DispatchError<E> {
fn from(err: io::Error) -> Self { fn from(err: io::Error) -> Self {
DispatchError::Io(err) DispatchError::Io(err)
} }

View File

@ -1,15 +1,15 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fmt::{Debug, Display};
use std::time::Instant; use std::time::Instant;
use actix_net::codec::Framed; use actix_net::codec::Framed;
use actix_net::service::Service; use actix_net::service::Service;
use futures::{Async, AsyncSink, Future, Poll, Sink, Stream}; use futures::{Async, AsyncSink, Future, Poll, Sink, Stream};
use log::Level::Debug;
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use tokio_timer::Delay; use tokio_timer::Delay;
use error::{Error, ParseError, PayloadError}; use error::{ParseError, PayloadError};
use payload::{Payload, PayloadSender, PayloadStatus, PayloadWriter}; use payload::{Payload, PayloadSender, PayloadStatus, PayloadWriter};
use body::Body; use body::Body;
@ -38,7 +38,7 @@ bitflags! {
/// Dispatcher for HTTP/1.1 protocol /// Dispatcher for HTTP/1.1 protocol
pub struct Dispatcher<T, S: Service> pub struct Dispatcher<T, S: Service>
where where
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
service: S, service: S,
flags: Flags, flags: Flags,
@ -61,7 +61,7 @@ enum Message {
enum State<S: Service> { enum State<S: Service> {
None, None,
Response(S::Future), ServiceCall(S::Future),
SendResponse(Option<OutMessage>), SendResponse(Option<OutMessage>),
SendResponseWithPayload(Option<(OutMessage, Body)>), SendResponseWithPayload(Option<(OutMessage, Body)>),
Payload(Body), Payload(Body),
@ -81,7 +81,7 @@ impl<T, S> Dispatcher<T, S>
where where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: Service<Request = Request, Response = Response>, S: Service<Request = Request, Response = Response>,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
/// Create http/1 dispatcher. /// Create http/1 dispatcher.
pub fn new(stream: T, config: ServiceConfig, service: S) -> Self { pub fn new(stream: T, config: ServiceConfig, service: S) -> Self {
@ -177,7 +177,7 @@ where
State::None => loop { State::None => loop {
break if let Some(msg) = self.messages.pop_front() { break if let Some(msg) = self.messages.pop_front() {
match msg { match msg {
Message::Item(req) => Some(self.handle_request(req)), Message::Item(req) => Some(self.handle_request(req)?),
Message::Error(res) => Some(State::SendResponse(Some( Message::Error(res) => Some(State::SendResponse(Some(
OutMessage::Response(res), OutMessage::Response(res),
))), ))),
@ -187,23 +187,23 @@ where
}; };
}, },
State::Payload(ref mut _body) => unimplemented!(), State::Payload(ref mut _body) => unimplemented!(),
State::Response(ref mut fut) => match fut.poll() { State::ServiceCall(ref mut fut) => match fut
Ok(Async::Ready(mut res)) => { .poll()
.map_err(DispatchError::Service)?
{
Async::Ready(mut res) => {
self.framed.get_codec_mut().prepare_te(&mut res); self.framed.get_codec_mut().prepare_te(&mut res);
if res.body().is_streaming() { let body = res.replace_body(Body::Empty);
unimplemented!() if body.is_empty() {
} else {
Some(State::SendResponse(Some(OutMessage::Response(res)))) Some(State::SendResponse(Some(OutMessage::Response(res))))
} else {
Some(State::SendResponseWithPayload(Some((
OutMessage::Response(res),
body,
))))
} }
} }
Ok(Async::NotReady) => None, Async::NotReady => None,
Err(err) => {
let err = err.into();
if log_enabled!(Debug) {
debug!("{:?}", err);
}
Some(State::SendResponse(Some(OutMessage::Response(err.into()))))
}
}, },
State::SendResponse(ref mut item) => { State::SendResponse(ref mut item) => {
let msg = item.take().expect("SendResponse is empty"); let msg = item.take().expect("SendResponse is empty");
@ -273,25 +273,24 @@ where
Ok(()) Ok(())
} }
fn handle_request(&mut self, req: Request) -> State<S> { fn handle_request(
&mut self, req: Request,
) -> Result<State<S>, DispatchError<S::Error>> {
let mut task = self.service.call(req); let mut task = self.service.call(req);
match task.poll() { match task.poll().map_err(DispatchError::Service)? {
Ok(Async::Ready(mut res)) => { Async::Ready(mut res) => {
self.framed.get_codec_mut().prepare_te(&mut res); self.framed.get_codec_mut().prepare_te(&mut res);
if res.body().is_streaming() { let body = res.replace_body(Body::Empty);
unimplemented!() if body.is_empty() {
Ok(State::SendResponse(Some(OutMessage::Response(res))))
} else { } else {
State::SendResponse(Some(OutMessage::Response(res))) Ok(State::SendResponseWithPayload(Some((
OutMessage::Response(res),
body,
))))
} }
} }
Ok(Async::NotReady) => State::Response(task), Async::NotReady => Ok(State::ServiceCall(task)),
Err(err) => {
let err = err.into();
if log_enabled!(Debug) {
debug!("{:?}", err);
}
State::SendResponse(Some(OutMessage::Response(err.into())))
}
} }
} }
@ -302,7 +301,7 @@ where
InMessage::Message(msg) => { InMessage::Message(msg) => {
// handle request early // handle request early
if self.state.is_empty() { if self.state.is_empty() {
self.state = self.handle_request(msg); self.state = self.handle_request(msg)?;
} else { } else {
self.messages.push_back(Message::Item(msg)); self.messages.push_back(Message::Item(msg));
} }
@ -445,7 +444,7 @@ impl<T, S> Future for Dispatcher<T, S>
where where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: Service<Request = Request, Response = Response>, S: Service<Request = Request, Response = Response>,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
type Item = (); type Item = ();
type Error = DispatchError<S::Error>; type Error = DispatchError<S::Error>;

View File

@ -1,3 +1,4 @@
use std::fmt::{Debug, Display};
use std::marker::PhantomData; use std::marker::PhantomData;
use actix_net::codec::Framed; use actix_net::codec::Framed;
@ -6,7 +7,7 @@ use futures::{future, Async, Future, Poll, Stream};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use config::ServiceConfig; use config::ServiceConfig;
use error::{DispatchError, Error, ParseError}; use error::{DispatchError, ParseError};
use request::Request; use request::Request;
use response::Response; use response::Response;
@ -24,7 +25,7 @@ impl<T, S> H1Service<T, S>
where where
S: NewService, S: NewService,
S::Service: Clone, S::Service: Clone,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
/// Create new `HttpService` instance. /// Create new `HttpService` instance.
pub fn new<F: IntoNewService<S>>(cfg: ServiceConfig, service: F) -> Self { pub fn new<F: IntoNewService<S>>(cfg: ServiceConfig, service: F) -> Self {
@ -41,7 +42,7 @@ where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: NewService<Request = Request, Response = Response> + Clone, S: NewService<Request = Request, Response = Response> + Clone,
S::Service: Clone, S::Service: Clone,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
type Request = T; type Request = T;
type Response = (); type Response = ();
@ -70,7 +71,7 @@ where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: NewService<Request = Request, Response = Response>, S: NewService<Request = Request, Response = Response>,
S::Service: Clone, S::Service: Clone,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
type Item = H1ServiceHandler<T, S::Service>; type Item = H1ServiceHandler<T, S::Service>;
type Error = S::InitError; type Error = S::InitError;
@ -94,7 +95,7 @@ pub struct H1ServiceHandler<T, S> {
impl<T, S> H1ServiceHandler<T, S> impl<T, S> H1ServiceHandler<T, S>
where where
S: Service<Request = Request, Response = Response> + Clone, S: Service<Request = Request, Response = Response> + Clone,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
fn new(cfg: ServiceConfig, srv: S) -> H1ServiceHandler<T, S> { fn new(cfg: ServiceConfig, srv: S) -> H1ServiceHandler<T, S> {
H1ServiceHandler { H1ServiceHandler {
@ -109,7 +110,7 @@ impl<T, S> Service for H1ServiceHandler<T, S>
where where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: Service<Request = Request, Response = Response> + Clone, S: Service<Request = Request, Response = Response> + Clone,
S::Error: Into<Error>, S::Error: Debug + Display,
{ {
type Request = T; type Request = T;
type Response = (); type Response = ();