diff --git a/Cargo.toml b/Cargo.toml index d992de647..a5fc597a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,12 +51,13 @@ actix-utils = "0.1.0" # actix-utils = { path="../actix-net/actix-utils/" } base64 = "0.9" +backtrace = "0.3" bitflags = "1.0" bytes = "0.4" byteorder = "1.2" cookie = { version="0.11", features=["percent-encode"] } +derive_more = "0.13" encoding = "0.2" -failure = "0.1.3" futures = "0.1" http = "0.1.8" httparse = "1.3" @@ -74,19 +75,11 @@ serde_urlencoded = "0.5.3" time = "0.1" tokio-tcp = "0.1" tokio-timer = "0.2" -trust-dns-proto = "0.5.0" -trust-dns-resolver = "0.10.0" -url = { version="1.7", features=["query_encoding"] } - -# native-tls -native-tls = { version="0.2", optional = true } +trust-dns-resolver = "0.10.1" # openssl openssl = { version="0.10", optional = true } -# rustls -rustls = { version = "^0.14", optional = true } - [dev-dependencies] actix-web = "0.7" env_logger = "0.5" diff --git a/src/client/error.rs b/src/client/error.rs index 815bc1edc..2a5df9c97 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -1,6 +1,6 @@ use std::io; -use failure::Fail; +use derive_more::{Display, From}; use trust_dns_resolver::error::ResolveError; #[cfg(feature = "ssl")] @@ -9,71 +9,52 @@ use openssl::ssl::{Error as SslError, HandshakeError}; use crate::error::{Error, ParseError}; /// A set of errors that can occur while connecting to an HTTP host -#[derive(Fail, Debug)] +#[derive(Debug, Display, From)] pub enum ConnectorError { /// Invalid URL - #[fail(display = "Invalid URL")] + #[display(fmt = "Invalid URL")] InvalidUrl(InvalidUrlKind), /// SSL feature is not enabled - #[fail(display = "SSL is not supported")] + #[display(fmt = "SSL is not supported")] SslIsNotSupported, /// SSL error #[cfg(feature = "ssl")] - #[fail(display = "{}", _0)] - SslError(#[cause] SslError), + #[display(fmt = "{}", _0)] + SslError(SslError), /// Failed to resolve the hostname - #[fail(display = "Failed resolving hostname: {}", _0)] + #[display(fmt = "Failed resolving hostname: {}", _0)] Resolver(ResolveError), /// No dns records - #[fail(display = "No dns records found for the input")] + #[display(fmt = "No dns records found for the input")] NoRecords, /// Connecting took too long - #[fail(display = "Timeout out while establishing connection")] + #[display(fmt = "Timeout out while establishing connection")] Timeout, /// Connector has been disconnected - #[fail(display = "Internal error: connector has been disconnected")] + #[display(fmt = "Internal error: connector has been disconnected")] Disconnected, /// Connection io error - #[fail(display = "{}", _0)] - IoError(io::Error), + #[display(fmt = "{}", _0)] + Io(io::Error), } -#[derive(Fail, Debug)] +#[derive(Debug, Display)] pub enum InvalidUrlKind { - #[fail(display = "Missing url scheme")] + #[display(fmt = "Missing url scheme")] MissingScheme, - #[fail(display = "Unknown url scheme")] + #[display(fmt = "Unknown url scheme")] UnknownScheme, - #[fail(display = "Missing host name")] + #[display(fmt = "Missing host name")] MissingHost, } -impl From for ConnectorError { - fn from(err: io::Error) -> ConnectorError { - ConnectorError::IoError(err) - } -} - -impl From for ConnectorError { - fn from(err: ResolveError) -> ConnectorError { - ConnectorError::Resolver(err) - } -} - -#[cfg(feature = "ssl")] -impl From for ConnectorError { - fn from(err: SslError) -> ConnectorError { - ConnectorError::SslError(err) - } -} - #[cfg(feature = "ssl")] impl From> for ConnectorError { fn from(err: HandshakeError) -> ConnectorError { @@ -90,10 +71,10 @@ impl From> for ConnectorError { } /// A set of errors that can occur during request sending and response reading -#[derive(Debug)] +#[derive(Debug, Display, From)] pub enum SendRequestError { /// Failed to connect to host - // #[fail(display = "Failed to connect to host: {}", _0)] + #[display(fmt = "Failed to connect to host: {}", _0)] Connector(ConnectorError), /// Error sending request Send(io::Error), @@ -102,27 +83,3 @@ pub enum SendRequestError { /// Error sending request body Body(Error), } - -impl From for SendRequestError { - fn from(err: io::Error) -> SendRequestError { - SendRequestError::Send(err) - } -} - -impl From for SendRequestError { - fn from(err: ConnectorError) -> SendRequestError { - SendRequestError::Connector(err) - } -} - -impl From for SendRequestError { - fn from(err: ParseError) -> SendRequestError { - SendRequestError::Response(err) - } -} - -impl From for SendRequestError { - fn from(err: Error) -> SendRequestError { - SendRequestError::Body(err) - } -} diff --git a/src/error.rs b/src/error.rs index 49602bd98..8af422fc8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,13 +1,14 @@ //! Error and Result module +use std::cell::RefCell; use std::io::Error as IoError; use std::str::Utf8Error; use std::string::FromUtf8Error; -use std::sync::Mutex; use std::{fmt, io, result}; // use actix::MailboxError; +use backtrace::Backtrace; use cookie; -use failure::{self, Backtrace, Fail}; +use derive_more::{Display, From}; use futures::Canceled; use http::uri::InvalidUri; use http::{header, Error as HttpError, StatusCode}; @@ -21,7 +22,7 @@ use tokio_timer::Error as TimerError; pub use cookie::ParseError as CookieParseError; use crate::body::Body; -use crate::response::{Response, ResponseParts}; +use crate::response::Response; /// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html) /// for actix web operations @@ -47,20 +48,6 @@ pub struct Error { } impl Error { - /// Deprecated way to reference the underlying response error. - #[deprecated( - since = "0.6.0", - note = "please use `Error::as_response_error()` instead" - )] - pub fn cause(&self) -> &ResponseError { - self.cause.as_ref() - } - - /// Returns a reference to the underlying cause of this `Error` as `Fail` - pub fn as_fail(&self) -> &Fail { - self.cause.as_fail() - } - /// Returns the reference to the underlying `ResponseError`. pub fn as_response_error(&self) -> &ResponseError { self.cause.as_ref() @@ -78,27 +65,27 @@ impl Error { } } - /// Attempts to downcast this `Error` to a particular `Fail` type by - /// reference. - /// - /// If the underlying error is not of type `T`, this will return `None`. - pub fn downcast_ref(&self) -> Option<&T> { - // in the most trivial way the cause is directly of the requested type. - if let Some(rv) = Fail::downcast_ref(self.cause.as_fail()) { - return Some(rv); - } + // /// Attempts to downcast this `Error` to a particular `Fail` type by + // /// reference. + // /// + // /// If the underlying error is not of type `T`, this will return `None`. + // pub fn downcast_ref(&self) -> Option<&T> { + // // in the most trivial way the cause is directly of the requested type. + // if let Some(rv) = Fail::downcast_ref(self.cause.as_fail()) { + // return Some(rv); + // } - // in the more complex case the error has been constructed from a failure - // error. This happens because we implement From by - // calling compat() and then storing it here. In failure this is - // represented by a failure::Error being wrapped in a failure::Compat. - // - // So we first downcast into that compat, to then further downcast through - // the failure's Error downcasting system into the original failure. - let compat: Option<&failure::Compat> = - Fail::downcast_ref(self.cause.as_fail()); - compat.and_then(|e| e.get_ref().downcast_ref()) - } + // // in the more complex case the error has been constructed from a failure + // // error. This happens because we implement From by + // // calling compat() and then storing it here. In failure this is + // // represented by a failure::Error being wrapped in a failure::Compat. + // // + // // So we first downcast into that compat, to then further downcast through + // // the failure's Error downcasting system into the original failure. + // let compat: Option<&failure::Compat> = + // Fail::downcast_ref(self.cause.as_fail()); + // compat.and_then(|e| e.get_ref().downcast_ref()) + // } /// Converts error to a response instance and set error message as response body pub fn response_with_message(self) -> Response { @@ -108,36 +95,41 @@ impl Error { } } -/// Helper trait to downcast a response error into a fail. -/// -/// This is currently not exposed because it's unclear if this is the best way -/// to achieve the downcasting on `Error` for which this is needed. -#[doc(hidden)] -pub trait InternalResponseErrorAsFail { - #[doc(hidden)] - fn as_fail(&self) -> &Fail; - #[doc(hidden)] - fn as_mut_fail(&mut self) -> &mut Fail; -} +// /// Helper trait to downcast a response error into a fail. +// /// +// /// This is currently not exposed because it's unclear if this is the best way +// /// to achieve the downcasting on `Error` for which this is needed. +// #[doc(hidden)] +// pub trait InternalResponseErrorAsFail { +// #[doc(hidden)] +// fn as_fail(&self) -> &Fail; +// #[doc(hidden)] +// fn as_mut_fail(&mut self) -> &mut Fail; +// } -#[doc(hidden)] -impl InternalResponseErrorAsFail for T { - fn as_fail(&self) -> &Fail { - self - } - fn as_mut_fail(&mut self) -> &mut Fail { - self - } -} +// #[doc(hidden)] +// impl InternalResponseErrorAsFail for T { +// fn as_fail(&self) -> &Fail { +// self +// } +// fn as_mut_fail(&mut self) -> &mut Fail { +// self +// } +// } /// Error that can be converted to `Response` -pub trait ResponseError: Fail + InternalResponseErrorAsFail { +pub trait ResponseError: fmt::Debug + fmt::Display { /// Create response for error /// /// Internal server error is generated by default. fn error_response(&self) -> Response { Response::new(StatusCode::INTERNAL_SERVER_ERROR) } + + /// Response + fn backtrace(&self) -> Option<&Backtrace> { + None + } } impl fmt::Display for Error { @@ -169,7 +161,7 @@ impl From for Response { } /// `Error` for any error that implements `ResponseError` -impl From for Error { +impl From for Error { fn from(err: T) -> Error { let backtrace = if err.backtrace().is_none() { Some(Backtrace::new()) @@ -183,17 +175,17 @@ impl From for Error { } } -/// Compatibility for `failure::Error` -impl ResponseError for failure::Compat where - T: fmt::Display + fmt::Debug + Sync + Send + 'static -{ -} +// /// Compatibility for `failure::Error` +// impl ResponseError for failure::Compat where +// T: fmt::Display + fmt::Debug + Sync + Send + 'static +// { +// } -impl From for Error { - fn from(err: failure::Error) -> Error { - err.compat().into() - } -} +// impl From for Error { +// fn from(err: failure::Error) -> Error { +// err.compat().into() +// } +// } /// `InternalServerError` for `JsonError` impl ResponseError for JsonError {} @@ -254,40 +246,40 @@ impl ResponseError for Canceled {} // impl ResponseError for MailboxError {} /// A set of errors that can occur during parsing HTTP streams -#[derive(Fail, Debug)] +#[derive(Debug, Display)] pub enum ParseError { /// An invalid `Method`, such as `GE.T`. - #[fail(display = "Invalid Method specified")] + #[display(fmt = "Invalid Method specified")] Method, /// An invalid `Uri`, such as `exam ple.domain`. - #[fail(display = "Uri error: {}", _0)] + #[display(fmt = "Uri error: {}", _0)] Uri(InvalidUri), /// An invalid `HttpVersion`, such as `HTP/1.1` - #[fail(display = "Invalid HTTP version specified")] + #[display(fmt = "Invalid HTTP version specified")] Version, /// An invalid `Header`. - #[fail(display = "Invalid Header provided")] + #[display(fmt = "Invalid Header provided")] Header, /// A message head is too large to be reasonable. - #[fail(display = "Message head is too large")] + #[display(fmt = "Message head is too large")] TooLarge, /// A message reached EOF, but is not complete. - #[fail(display = "Message is incomplete")] + #[display(fmt = "Message is incomplete")] Incomplete, /// An invalid `Status`, such as `1337 ELITE`. - #[fail(display = "Invalid Status provided")] + #[display(fmt = "Invalid Status provided")] Status, /// A timeout occurred waiting for an IO event. #[allow(dead_code)] - #[fail(display = "Timeout")] + #[display(fmt = "Timeout")] Timeout, /// An `io::Error` that occurred while trying to read or write to a network /// stream. - #[fail(display = "IO error: {}", _0)] - Io(#[cause] IoError), + #[display(fmt = "IO error: {}", _0)] + Io(IoError), /// Parsing a field as string failed - #[fail(display = "UTF8 error: {}", _0)] - Utf8(#[cause] Utf8Error), + #[display(fmt = "UTF8 error: {}", _0)] + Utf8(Utf8Error), } /// Return `BadRequest` for `ParseError` @@ -335,20 +327,20 @@ impl From for ParseError { } } -#[derive(Fail, Debug)] +#[derive(Display, Debug)] /// A set of errors that can occur during payload parsing pub enum PayloadError { /// A payload reached EOF, but is not complete. - #[fail(display = "A payload reached EOF, but is not complete.")] + #[display(fmt = "A payload reached EOF, but is not complete.")] Incomplete(Option), /// Content encoding stream corruption - #[fail(display = "Can not decode content-encoding.")] + #[display(fmt = "Can not decode content-encoding.")] EncodingCorrupted, /// A payload reached size limit. - #[fail(display = "A payload reached size limit.")] + #[display(fmt = "A payload reached size limit.")] Overflow, /// A payload length is unknown. - #[fail(display = "A payload length is unknown.")] + #[display(fmt = "A payload length is unknown.")] UnknownLength, } @@ -378,44 +370,44 @@ impl ResponseError for cookie::ParseError { } } -#[derive(Debug)] +#[derive(Debug, Display)] /// A set of errors that can occur during dispatching http requests pub enum DispatchError { /// Service error - // #[fail(display = "Application specific error: {}", _0)] + #[display(fmt = "Service specific error: {:?}", _0)] Service(E), /// An `io::Error` that occurred while trying to read or write to a network /// stream. - // #[fail(display = "IO error: {}", _0)] + #[display(fmt = "IO error: {}", _0)] Io(io::Error), /// Http request parse error. - // #[fail(display = "Parse error: {}", _0)] + #[display(fmt = "Parse error: {}", _0)] Parse(ParseError), /// The first request did not complete within the specified timeout. - // #[fail(display = "The first request did not complete within the specified timeout")] + #[display(fmt = "The first request did not complete within the specified timeout")] SlowRequestTimeout, /// Disconnect timeout. Makes sense for ssl streams. - // #[fail(display = "Connection shutdown timeout")] + #[display(fmt = "Connection shutdown timeout")] DisconnectTimeout, /// Payload is not consumed - // #[fail(display = "Task is completed but request's payload is not consumed")] + #[display(fmt = "Task is completed but request's payload is not consumed")] PayloadIsNotConsumed, /// Malformed request - // #[fail(display = "Malformed request")] + #[display(fmt = "Malformed request")] MalformedRequest, /// Internal error - // #[fail(display = "Internal error")] + #[display(fmt = "Internal error")] InternalError, /// Unknown error - // #[fail(display = "Unknown error")] + #[display(fmt = "Unknown error")] Unknown, } @@ -432,13 +424,13 @@ impl From for DispatchError { } /// A set of error that can occure during parsing content type -#[derive(Fail, PartialEq, Debug)] +#[derive(PartialEq, Debug, Display)] pub enum ContentTypeError { /// Can not parse content type - #[fail(display = "Can not parse content type")] + #[display(fmt = "Can not parse content type")] ParseError, /// Unknown content encoding - #[fail(display = "Unknown content encoding")] + #[display(fmt = "Unknown content encoding")] UnknownEncoding, } @@ -450,28 +442,26 @@ impl ResponseError for ContentTypeError { } /// A set of errors that can occur during parsing urlencoded payloads -#[derive(Fail, Debug)] +#[derive(Debug, Display, From)] pub enum UrlencodedError { /// Can not decode chunked transfer encoding - #[fail(display = "Can not decode chunked transfer encoding")] + #[display(fmt = "Can not decode chunked transfer encoding")] Chunked, /// Payload size is bigger than allowed. (default: 256kB) - #[fail( - display = "Urlencoded payload size is bigger than allowed. (default: 256kB)" - )] + #[display(fmt = "Urlencoded payload size is bigger than allowed. (default: 256kB)")] Overflow, /// Payload size is now known - #[fail(display = "Payload size is now known")] + #[display(fmt = "Payload size is now known")] UnknownLength, /// Content type error - #[fail(display = "Content type error")] + #[display(fmt = "Content type error")] ContentType, /// Parse error - #[fail(display = "Parse error")] + #[display(fmt = "Parse error")] Parse, /// Payload error - #[fail(display = "Error that occur during reading payload: {}", _0)] - Payload(#[cause] PayloadError), + #[display(fmt = "Error that occur during reading payload: {}", _0)] + Payload(PayloadError), } /// Return `BadRequest` for `UrlencodedError` @@ -485,27 +475,21 @@ impl ResponseError for UrlencodedError { } } -impl From for UrlencodedError { - fn from(err: PayloadError) -> UrlencodedError { - UrlencodedError::Payload(err) - } -} - /// A set of errors that can occur during parsing json payloads -#[derive(Fail, Debug)] +#[derive(Debug, Display, From)] pub enum JsonPayloadError { /// Payload size is bigger than allowed. (default: 256kB) - #[fail(display = "Json payload size is bigger than allowed. (default: 256kB)")] + #[display(fmt = "Json payload size is bigger than allowed. (default: 256kB)")] Overflow, /// Content type error - #[fail(display = "Content type error")] + #[display(fmt = "Content type error")] ContentType, /// Deserialize error - #[fail(display = "Json deserialize error: {}", _0)] - Deserialize(#[cause] JsonError), + #[display(fmt = "Json deserialize error: {}", _0)] + Deserialize(JsonError), /// Payload error - #[fail(display = "Error that occur during reading payload: {}", _0)] - Payload(#[cause] PayloadError), + #[display(fmt = "Error that occur during reading payload: {}", _0)] + Payload(PayloadError), } /// Return `BadRequest` for `UrlencodedError` @@ -518,19 +502,8 @@ impl ResponseError for JsonPayloadError { } } -impl From for JsonPayloadError { - fn from(err: PayloadError) -> JsonPayloadError { - JsonPayloadError::Payload(err) - } -} - -impl From for JsonPayloadError { - fn from(err: JsonError) -> JsonPayloadError { - JsonPayloadError::Deserialize(err) - } -} - /// Error type returned when reading body as lines. +#[derive(From)] pub enum ReadlinesError { /// Error when decoding a line. EncodingError, @@ -542,18 +515,6 @@ pub enum ReadlinesError { ContentTypeError(ContentTypeError), } -impl From for ReadlinesError { - fn from(err: PayloadError) -> Self { - ReadlinesError::PayloadError(err) - } -} - -impl From for ReadlinesError { - fn from(err: ContentTypeError) -> Self { - ReadlinesError::ContentTypeError(err) - } -} - /// Helper type that can wrap any error and generate custom response. /// /// In following example any `io::Error` will be converted into "BAD REQUEST" @@ -578,7 +539,7 @@ pub struct InternalError { enum InternalErrorType { Status(StatusCode), - Response(Box>>), + Response(RefCell>), } impl InternalError { @@ -593,27 +554,17 @@ impl InternalError { /// Create `InternalError` with predefined `Response`. pub fn from_response(cause: T, response: Response) -> Self { - let resp = response.into_parts(); InternalError { cause, - status: InternalErrorType::Response(Box::new(Mutex::new(Some(resp)))), + status: InternalErrorType::Response(RefCell::new(Some(response))), backtrace: Backtrace::new(), } } } -impl Fail for InternalError -where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, -{ - fn backtrace(&self) -> Option<&Backtrace> { - Some(&self.backtrace) - } -} - impl fmt::Debug for InternalError where - T: Send + Sync + fmt::Debug + 'static, + T: fmt::Debug + 'static, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.cause, f) @@ -622,7 +573,7 @@ where impl fmt::Display for InternalError where - T: Send + Sync + fmt::Display + 'static, + T: fmt::Display + 'static, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.cause, f) @@ -631,14 +582,18 @@ where impl ResponseError for InternalError where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { + fn backtrace(&self) -> Option<&Backtrace> { + Some(&self.backtrace) + } + fn error_response(&self) -> Response { match self.status { InternalErrorType::Status(st) => Response::new(st), InternalErrorType::Response(ref resp) => { - if let Some(resp) = resp.lock().unwrap().take() { - Response::<()>::from_parts(resp) + if let Some(resp) = resp.borrow_mut().take() { + resp } else { Response::new(StatusCode::INTERNAL_SERVER_ERROR) } @@ -659,7 +614,7 @@ impl From for Error { #[allow(non_snake_case)] pub fn ErrorBadRequest(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::BAD_REQUEST).into() } @@ -669,7 +624,7 @@ where #[allow(non_snake_case)] pub fn ErrorUnauthorized(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::UNAUTHORIZED).into() } @@ -679,7 +634,7 @@ where #[allow(non_snake_case)] pub fn ErrorForbidden(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::FORBIDDEN).into() } @@ -689,7 +644,7 @@ where #[allow(non_snake_case)] pub fn ErrorNotFound(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::NOT_FOUND).into() } @@ -699,7 +654,7 @@ where #[allow(non_snake_case)] pub fn ErrorMethodNotAllowed(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED).into() } @@ -709,7 +664,7 @@ where #[allow(non_snake_case)] pub fn ErrorRequestTimeout(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::REQUEST_TIMEOUT).into() } @@ -719,7 +674,7 @@ where #[allow(non_snake_case)] pub fn ErrorConflict(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::CONFLICT).into() } @@ -729,7 +684,7 @@ where #[allow(non_snake_case)] pub fn ErrorGone(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::GONE).into() } @@ -739,7 +694,7 @@ where #[allow(non_snake_case)] pub fn ErrorPreconditionFailed(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::PRECONDITION_FAILED).into() } @@ -749,7 +704,7 @@ where #[allow(non_snake_case)] pub fn ErrorExpectationFailed(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::EXPECTATION_FAILED).into() } @@ -759,7 +714,7 @@ where #[allow(non_snake_case)] pub fn ErrorInternalServerError(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR).into() } @@ -769,7 +724,7 @@ where #[allow(non_snake_case)] pub fn ErrorNotImplemented(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::NOT_IMPLEMENTED).into() } @@ -779,7 +734,7 @@ where #[allow(non_snake_case)] pub fn ErrorBadGateway(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::BAD_GATEWAY).into() } @@ -789,7 +744,7 @@ where #[allow(non_snake_case)] pub fn ErrorServiceUnavailable(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::SERVICE_UNAVAILABLE).into() } @@ -799,7 +754,7 @@ where #[allow(non_snake_case)] pub fn ErrorGatewayTimeout(err: T) -> Error where - T: Send + Sync + fmt::Debug + fmt::Display + 'static, + T: fmt::Debug + fmt::Display + 'static, { InternalError::new(err, StatusCode::GATEWAY_TIMEOUT).into() } @@ -808,10 +763,8 @@ where mod tests { use super::*; use cookie::ParseError as CookieParseError; - use failure; use http::{Error as HttpError, StatusCode}; use httparse; - use std::env; use std::error::Error as StdError; use std::io; @@ -829,11 +782,10 @@ mod tests { } #[test] - fn test_as_fail() { + fn test_as_response() { let orig = io::Error::new(io::ErrorKind::Other, "other"); - let desc = orig.description().to_owned(); - let e = ParseError::Io(orig); - assert_eq!(format!("{}", e.cause().unwrap()), desc); + let e: Error = ParseError::Io(orig).into(); + assert_eq!(format!("{}", e.as_response_error()), "IO error: other"); } #[test] @@ -847,7 +799,7 @@ mod tests { let orig = io::Error::new(io::ErrorKind::Other, "other"); let desc = orig.description().to_owned(); let e = Error::from(orig); - assert_eq!(format!("{}", e.as_fail()), desc); + assert_eq!(format!("{}", e.as_response_error()), desc); } #[test] @@ -881,7 +833,7 @@ mod tests { ($from:expr => $error:pat) => { match ParseError::from($from) { e @ $error => { - let desc = format!("{}", e.cause().unwrap()); + let desc = format!("{}", e); assert_eq!(desc, $from.description().to_owned()); } _ => unreachable!("{:?}", $from), @@ -891,8 +843,7 @@ mod tests { #[test] fn test_from() { - from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => ParseError::Io(..)); - + // from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => ParseError::Io(..)); from!(httparse::Error::HeaderName => ParseError::Header); from!(httparse::Error::HeaderName => ParseError::Header); from!(httparse::Error::HeaderValue => ParseError::Header); @@ -903,22 +854,22 @@ mod tests { from!(httparse::Error::Version => ParseError::Version); } - #[test] - fn failure_error() { - const NAME: &str = "RUST_BACKTRACE"; - let old_tb = env::var(NAME); - env::set_var(NAME, "0"); - let error = failure::err_msg("Hello!"); - let resp: Error = error.into(); - assert_eq!( - format!("{:?}", resp), - "Compat { error: ErrorMessage { msg: \"Hello!\" } }\n\n" - ); - match old_tb { - Ok(x) => env::set_var(NAME, x), - _ => env::remove_var(NAME), - } - } + // #[test] + // fn failure_error() { + // const NAME: &str = "RUST_BACKTRACE"; + // let old_tb = env::var(NAME); + // env::set_var(NAME, "0"); + // let error = failure::err_msg("Hello!"); + // let resp: Error = error.into(); + // assert_eq!( + // format!("{:?}", resp), + // "Compat { error: ErrorMessage { msg: \"Hello!\" } }\n\n" + // ); + // match old_tb { + // Ok(x) => env::set_var(NAME, x), + // _ => env::remove_var(NAME), + // } + // } #[test] fn test_internal_error() { @@ -928,31 +879,31 @@ mod tests { assert_eq!(resp.status(), StatusCode::OK); } - #[test] - fn test_error_downcasting_direct() { - #[derive(Debug, Fail)] - #[fail(display = "demo error")] - struct DemoError; + // #[test] + // fn test_error_downcasting_direct() { + // #[derive(Debug, Display)] + // #[display(fmt = "demo error")] + // struct DemoError; - impl ResponseError for DemoError {} + // impl ResponseError for DemoError {} - let err: Error = DemoError.into(); - let err_ref: &DemoError = err.downcast_ref().unwrap(); - assert_eq!(err_ref.to_string(), "demo error"); - } + // let err: Error = DemoError.into(); + // let err_ref: &DemoError = err.downcast_ref().unwrap(); + // assert_eq!(err_ref.to_string(), "demo error"); + // } - #[test] - fn test_error_downcasting_compat() { - #[derive(Debug, Fail)] - #[fail(display = "demo error")] - struct DemoError; + // #[test] + // fn test_error_downcasting_compat() { + // #[derive(Debug, Display)] + // #[display(fmt = "demo error")] + // struct DemoError; - impl ResponseError for DemoError {} + // impl ResponseError for DemoError {} - let err: Error = failure::Error::from(DemoError).into(); - let err_ref: &DemoError = err.downcast_ref().unwrap(); - assert_eq!(err_ref.to_string(), "demo error"); - } + // let err: Error = failure::Error::from(DemoError).into(); + // let err_ref: &DemoError = err.downcast_ref().unwrap(); + // assert_eq!(err_ref.to_string(), "demo error"); + // } #[test] fn test_error_helpers() { diff --git a/src/response.rs b/src/response.rs index 5cff612f7..49f2b63fb 100644 --- a/src/response.rs +++ b/src/response.rs @@ -240,17 +240,6 @@ impl Response { pub(crate) fn release(self) { ResponsePool::release(self.0); } - - pub(crate) fn into_parts(self) -> ResponseParts { - self.0.into_parts() - } - - pub(crate) fn from_parts(parts: ResponseParts) -> Response { - Response( - Box::new(InnerResponse::from_parts(parts)), - ResponseBody::Body(Body::Empty), - ) - } } impl fmt::Debug for Response { @@ -736,11 +725,6 @@ struct InnerResponse { pool: &'static ResponsePool, } -pub(crate) struct ResponseParts { - head: ResponseHead, - error: Option, -} - impl InnerResponse { #[inline] fn new(status: StatusCode, pool: &'static ResponsePool) -> InnerResponse { @@ -757,23 +741,6 @@ impl InnerResponse { error: None, } } - - /// This is for failure, we can not have Send + Sync on Streaming and Actor response - fn into_parts(self) -> ResponseParts { - ResponseParts { - head: self.head, - error: self.error, - } - } - - fn from_parts(parts: ResponseParts) -> InnerResponse { - InnerResponse { - head: parts.head, - response_size: 0, - error: parts.error, - pool: ResponsePool::pool(), - } - } } /// Internal use only! diff --git a/src/ws/client/error.rs b/src/ws/client/error.rs index 02c723755..1eccb0b95 100644 --- a/src/ws/client/error.rs +++ b/src/ws/client/error.rs @@ -2,82 +2,52 @@ use std::io; use actix_connector::ConnectorError; -use failure::Fail; +use derive_more::{Display, From}; use http::{header::HeaderValue, Error as HttpError, StatusCode}; use crate::error::ParseError; use crate::ws::ProtocolError; /// Websocket client error -#[derive(Fail, Debug)] +#[derive(Debug, Display, From)] pub enum ClientError { /// Invalid url - #[fail(display = "Invalid url")] + #[display(fmt = "Invalid url")] InvalidUrl, /// Invalid response status - #[fail(display = "Invalid response status")] + #[display(fmt = "Invalid response status")] InvalidResponseStatus(StatusCode), /// Invalid upgrade header - #[fail(display = "Invalid upgrade header")] + #[display(fmt = "Invalid upgrade header")] InvalidUpgradeHeader, /// Invalid connection header - #[fail(display = "Invalid connection header")] + #[display(fmt = "Invalid connection header")] InvalidConnectionHeader(HeaderValue), /// Missing CONNECTION header - #[fail(display = "Missing CONNECTION header")] + #[display(fmt = "Missing CONNECTION header")] MissingConnectionHeader, /// Missing SEC-WEBSOCKET-ACCEPT header - #[fail(display = "Missing SEC-WEBSOCKET-ACCEPT header")] + #[display(fmt = "Missing SEC-WEBSOCKET-ACCEPT header")] MissingWebSocketAcceptHeader, /// Invalid challenge response - #[fail(display = "Invalid challenge response")] + #[display(fmt = "Invalid challenge response")] InvalidChallengeResponse(String, HeaderValue), /// Http parsing error - #[fail(display = "Http parsing error")] - Http(#[cause] HttpError), + #[display(fmt = "Http parsing error")] + Http(HttpError), /// Response parsing error - #[fail(display = "Response parsing error: {}", _0)] - ParseError(#[cause] ParseError), + #[display(fmt = "Response parsing error: {}", _0)] + ParseError(ParseError), /// Protocol error - #[fail(display = "{}", _0)] - Protocol(#[cause] ProtocolError), + #[display(fmt = "{}", _0)] + Protocol(ProtocolError), /// Connect error - #[fail(display = "Connector error: {:?}", _0)] + #[display(fmt = "Connector error: {:?}", _0)] Connect(ConnectorError), /// IO Error - #[fail(display = "{}", _0)] - Io(#[cause] io::Error), + #[display(fmt = "{}", _0)] + Io(io::Error), /// "Disconnected" - #[fail(display = "Disconnected")] + #[display(fmt = "Disconnected")] Disconnected, } - -impl From for ClientError { - fn from(err: HttpError) -> ClientError { - ClientError::Http(err) - } -} - -impl From for ClientError { - fn from(err: ConnectorError) -> ClientError { - ClientError::Connect(err) - } -} - -impl From for ClientError { - fn from(err: ProtocolError) -> ClientError { - ClientError::Protocol(err) - } -} - -impl From for ClientError { - fn from(err: io::Error) -> ClientError { - ClientError::Io(err) - } -} - -impl From for ClientError { - fn from(err: ParseError) -> ClientError { - ClientError::ParseError(err) - } -} diff --git a/src/ws/mod.rs b/src/ws/mod.rs index 02667c964..2d629c73b 100644 --- a/src/ws/mod.rs +++ b/src/ws/mod.rs @@ -5,7 +5,7 @@ //! communicate with the peer. use std::io; -use failure::Fail; +use derive_more::{Display, From}; use http::{header, Method, StatusCode}; use crate::error::ResponseError; @@ -28,65 +28,59 @@ pub use self::service::VerifyWebSockets; pub use self::transport::Transport; /// Websocket protocol errors -#[derive(Fail, Debug)] +#[derive(Debug, Display, From)] pub enum ProtocolError { /// Received an unmasked frame from client - #[fail(display = "Received an unmasked frame from client")] + #[display(fmt = "Received an unmasked frame from client")] UnmaskedFrame, /// Received a masked frame from server - #[fail(display = "Received a masked frame from server")] + #[display(fmt = "Received a masked frame from server")] MaskedFrame, /// Encountered invalid opcode - #[fail(display = "Invalid opcode: {}", _0)] + #[display(fmt = "Invalid opcode: {}", _0)] InvalidOpcode(u8), /// Invalid control frame length - #[fail(display = "Invalid control frame length: {}", _0)] + #[display(fmt = "Invalid control frame length: {}", _0)] InvalidLength(usize), /// Bad web socket op code - #[fail(display = "Bad web socket op code")] + #[display(fmt = "Bad web socket op code")] BadOpCode, /// A payload reached size limit. - #[fail(display = "A payload reached size limit.")] + #[display(fmt = "A payload reached size limit.")] Overflow, /// Continuation is not supported - #[fail(display = "Continuation is not supported.")] + #[display(fmt = "Continuation is not supported.")] NoContinuation, /// Bad utf-8 encoding - #[fail(display = "Bad utf-8 encoding.")] + #[display(fmt = "Bad utf-8 encoding.")] BadEncoding, /// Io error - #[fail(display = "io error: {}", _0)] - Io(#[cause] io::Error), + #[display(fmt = "io error: {}", _0)] + Io(io::Error), } impl ResponseError for ProtocolError {} -impl From for ProtocolError { - fn from(err: io::Error) -> ProtocolError { - ProtocolError::Io(err) - } -} - /// Websocket handshake errors -#[derive(Fail, PartialEq, Debug)] +#[derive(PartialEq, Debug, Display)] pub enum HandshakeError { /// Only get method is allowed - #[fail(display = "Method not allowed")] + #[display(fmt = "Method not allowed")] GetMethodRequired, /// Upgrade header if not set to websocket - #[fail(display = "Websocket upgrade is expected")] + #[display(fmt = "Websocket upgrade is expected")] NoWebsocketUpgrade, /// Connection header is not set to upgrade - #[fail(display = "Connection upgrade is expected")] + #[display(fmt = "Connection upgrade is expected")] NoConnectionUpgrade, /// Websocket version header is not set - #[fail(display = "Websocket version header is required")] + #[display(fmt = "Websocket version header is required")] NoVersionHeader, /// Unsupported websocket version - #[fail(display = "Unsupported version")] + #[display(fmt = "Unsupported version")] UnsupportedVersion, /// Websocket key is not set or wrong - #[fail(display = "Unknown websocket key")] + #[display(fmt = "Unknown websocket key")] BadWebsocketKey, }