mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-27 17:22:57 +01:00
Add support for downcasting response errors (#986)
* Add support for downcasting response errors * Added test for error casting
This commit is contained in:
parent
fbdda8acb1
commit
29098f8397
@ -4,6 +4,7 @@ use std::io::Write;
|
|||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
use std::{fmt, io, result};
|
use std::{fmt, io, result};
|
||||||
|
use std::any::TypeId;
|
||||||
|
|
||||||
pub use actix_threadpool::BlockingError;
|
pub use actix_threadpool::BlockingError;
|
||||||
use actix_utils::timeout::TimeoutError;
|
use actix_utils::timeout::TimeoutError;
|
||||||
@ -51,6 +52,11 @@ impl Error {
|
|||||||
pub fn as_response_error(&self) -> &dyn ResponseError {
|
pub fn as_response_error(&self) -> &dyn ResponseError {
|
||||||
self.cause.as_ref()
|
self.cause.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Similar to `as_response_error` but downcasts.
|
||||||
|
pub fn as_error<T: ResponseError + 'static>(&self) -> Option<&T> {
|
||||||
|
ResponseError::downcast_ref(self.cause.as_ref())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error that can be converted to `Response`
|
/// Error that can be converted to `Response`
|
||||||
@ -73,6 +79,22 @@ pub trait ResponseError: fmt::Debug + fmt::Display {
|
|||||||
);
|
);
|
||||||
resp.set_body(Body::from(buf))
|
resp.set_body(Body::from(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn __private_get_type_id__(&self) -> TypeId where Self: 'static {
|
||||||
|
TypeId::of::<Self>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseError + 'static {
|
||||||
|
/// Downcasts a response error to a specific type.
|
||||||
|
pub fn downcast_ref<T: ResponseError + 'static>(&self) -> Option<&T> {
|
||||||
|
if self.__private_get_type_id__() == TypeId::of::<T>() {
|
||||||
|
unsafe { Some(&*(self as *const ResponseError as *const T)) }
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -1044,6 +1066,16 @@ mod tests {
|
|||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_error_casting() {
|
||||||
|
let err = PayloadError::Overflow;
|
||||||
|
let resp_err: &ResponseError = &err;
|
||||||
|
let err = resp_err.downcast_ref::<PayloadError>().unwrap();
|
||||||
|
assert_eq!(err.to_string(), "A payload reached size limit.");
|
||||||
|
let not_err = resp_err.downcast_ref::<ContentTypeError>();
|
||||||
|
assert!(not_err.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_helpers() {
|
fn test_error_helpers() {
|
||||||
let r: Response = ErrorBadRequest("err").into();
|
let r: Response = ErrorBadRequest("err").into();
|
||||||
|
Loading…
Reference in New Issue
Block a user