Implement `failure::Error` for `actix_web::Error`.

Without that implementation it is hard to use `actix_web::Error` with
failure or similar crates. This change also simplifies `impl
actix_web::Error`.
This commit is contained in:
Marcin Mielniczuk 2019-01-31 15:59:30 +01:00
parent 9968afe4a6
commit cd91693900
No known key found for this signature in database
GPG Key ID: 2CF0CE66660B8CC9
1 changed files with 26 additions and 24 deletions

View File

@ -44,41 +44,33 @@ pub type Result<T, E = Error> = result::Result<T, E>;
/// for it that can be used to create an http response from it this means that /// for it that can be used to create an http response from it this means that
/// if you have access to an actix `Error` you can always get a /// if you have access to an actix `Error` you can always get a
/// `ResponseError` reference from it. /// `ResponseError` reference from it.
///
/// This type supports conversion to the `failure::Error` type. To use this
/// type as `std::error::Error`, you can use the `compat` method from `failure`.
pub struct Error { pub struct Error {
cause: Box<ResponseError>, cause: Box<ResponseError>,
backtrace: Option<Backtrace>, backtrace: Option<Backtrace>,
} }
impl Error { impl failure::Fail for 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()
}
/// Returns a reference to the Backtrace carried by this error, if it /// Returns a reference to the Backtrace carried by this error, if it
/// carries one. /// carries one.
/// ///
/// This uses the same `Backtrace` type that `failure` uses. /// This uses the same `Backtrace` type that `failure` uses.
pub fn backtrace(&self) -> &Backtrace { fn backtrace(&self) -> Option<&Backtrace> {
if let Some(bt) = self.cause.backtrace() { let backtrace = if let Some(bt) = self.cause.backtrace() {
bt bt
} else { } else {
self.backtrace.as_ref().unwrap() self.backtrace.as_ref().unwrap()
} };
Some(backtrace)
}
}
impl Error {
/// Returns the reference to the underlying `ResponseError`.
pub fn as_response_error(&self) -> &ResponseError {
self.cause.as_ref()
} }
/// Attempts to downcast this `Error` to a particular `Fail` type by /// Attempts to downcast this `Error` to a particular `Fail` type by
@ -1137,7 +1129,7 @@ where
mod tests { mod tests {
use super::*; use super::*;
use cookie::ParseError as CookieParseError; use cookie::ParseError as CookieParseError;
use failure; use failure::{self, Fail, AsFail};
use http::{Error as HttpError, StatusCode}; use http::{Error as HttpError, StatusCode};
use httparse; use httparse;
use std::env; use std::env;
@ -1206,6 +1198,16 @@ mod tests {
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
} }
#[test]
fn test_conversion() {
// this should just compile
let err: Error = ParseError::Incomplete.into();
let _: failure::Error = err.into();
let err: Error = ParseError::Incomplete.into();
let _: Box<dyn std::error::Error> = Box::new(err.compat());
}
#[test] #[test]
fn test_expect_error() { fn test_expect_error() {
let resp: HttpResponse = ExpectError::Encoding.error_response(); let resp: HttpResponse = ExpectError::Encoding.error_response();