mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 16:02:59 +01:00
refactor helper error types
This commit is contained in:
parent
552320bae2
commit
9180625dfd
@ -5,7 +5,7 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
|||||||
workspace = "../.."
|
workspace = "../.."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.4"
|
env_logger = "0.5"
|
||||||
actix = "0.4"
|
actix = "0.4"
|
||||||
actix-web = { path = "../../" }
|
actix-web = { path = "../../" }
|
||||||
|
|
||||||
|
@ -5,6 +5,6 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
|||||||
workspace = "../.."
|
workspace = "../.."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.4"
|
env_logger = "0.5"
|
||||||
actix = "0.4"
|
actix = "0.4"
|
||||||
actix-web = { path = "../../" }
|
actix-web = { path = "../../" }
|
||||||
|
@ -6,6 +6,6 @@ workspace = "../.."
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "*"
|
futures = "*"
|
||||||
env_logger = "0.4"
|
env_logger = "0.5"
|
||||||
actix = "0.4"
|
actix = "0.4"
|
||||||
actix-web = { path = "../../" }
|
actix-web = { path = "../../" }
|
||||||
|
@ -5,7 +5,7 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
|||||||
workspace = "../.."
|
workspace = "../.."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.4"
|
env_logger = "0.5"
|
||||||
actix = "0.4"
|
actix = "0.4"
|
||||||
actix-web = { path = "../../" }
|
actix-web = { path = "../../" }
|
||||||
tera = "*"
|
tera = "*"
|
||||||
|
@ -9,6 +9,6 @@ name = "server"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.4"
|
env_logger = "0.5"
|
||||||
actix = "^0.4.2"
|
actix = "^0.4.2"
|
||||||
actix-web = { path = "../../", features=["alpn"] }
|
actix-web = { path = "../../", features=["alpn"] }
|
||||||
|
191
src/error.rs
191
src/error.rs
@ -68,8 +68,8 @@ impl fmt::Display for Error {
|
|||||||
|
|
||||||
impl fmt::Debug for Error {
|
impl fmt::Debug for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.backtrace.is_none() {
|
if let Some(bt) = self.cause.backtrace() {
|
||||||
fmt::Debug::fmt(&self.cause, f)
|
write!(f, "{:?}\n\n{:?}", &self.cause, bt)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{:?}\n\n{:?}", &self.cause, self.backtrace.as_ref().unwrap())
|
write!(f, "{:?}\n\n{:?}", &self.cause, self.backtrace.as_ref().unwrap())
|
||||||
}
|
}
|
||||||
@ -495,52 +495,7 @@ impl From<UrlParseError> for UrlGenerationError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! ERROR_WRAP {
|
/// Helper type that can wrap any error and generate custom response.
|
||||||
($type:ty, $status:expr) => {
|
|
||||||
unsafe impl<T> Sync for $type {}
|
|
||||||
unsafe impl<T> Send for $type {}
|
|
||||||
|
|
||||||
impl<T> $type {
|
|
||||||
pub fn cause(&self) -> &T {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Display + fmt::Debug + 'static> Fail for $type {}
|
|
||||||
impl<T: Fail> Fail for $type {
|
|
||||||
fn backtrace(&self) -> Option<&Backtrace> {
|
|
||||||
self.cause().backtrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Display + 'static> fmt::Display for $type {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
fmt::Display::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ResponseError for $type
|
|
||||||
where T: Send + Sync + fmt::Debug + fmt::Display + 'static
|
|
||||||
{
|
|
||||||
fn error_response(&self) -> HttpResponse {
|
|
||||||
HttpResponse::new($status, Body::Empty)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Responder for $type
|
|
||||||
where T: Send + Sync + fmt::Debug + fmt::Display + 'static
|
|
||||||
{
|
|
||||||
type Item = HttpResponse;
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn respond_to(self, _: HttpRequest) -> Result<HttpResponse, Error> {
|
|
||||||
Err(self.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper type that can wrap any error and generate *BAD REQUEST* response.
|
|
||||||
///
|
///
|
||||||
/// In following example any `io::Error` will be converted into "BAD REQUEST" response
|
/// In following example any `io::Error` will be converted into "BAD REQUEST" response
|
||||||
/// as opposite to *INNTERNAL SERVER ERROR* which is defined by default.
|
/// as opposite to *INNTERNAL SERVER ERROR* which is defined by default.
|
||||||
@ -556,59 +511,133 @@ macro_rules! ERROR_WRAP {
|
|||||||
/// }
|
/// }
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug)]
|
pub struct InternalError<T> {
|
||||||
pub struct ErrorBadRequest<T>(pub T);
|
cause: T,
|
||||||
ERROR_WRAP!(ErrorBadRequest<T>, StatusCode::BAD_REQUEST);
|
status: StatusCode,
|
||||||
|
backtrace: Backtrace,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Sync for InternalError<T> {}
|
||||||
|
unsafe impl<T> Send for InternalError<T> {}
|
||||||
|
|
||||||
|
impl<T> InternalError<T> {
|
||||||
|
pub fn new(err: T, status: StatusCode) -> Self {
|
||||||
|
InternalError {
|
||||||
|
cause: err,
|
||||||
|
status: status,
|
||||||
|
backtrace: Backtrace::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Fail for InternalError<T>
|
||||||
|
where T: Send + Sync + fmt::Display + fmt::Debug + 'static
|
||||||
|
{
|
||||||
|
fn backtrace(&self) -> Option<&Backtrace> {
|
||||||
|
Some(&self.backtrace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> fmt::Debug for InternalError<T>
|
||||||
|
where T: Send + Sync + fmt::Display + fmt::Debug + 'static
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Debug::fmt(&self.cause, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> fmt::Display for InternalError<T>
|
||||||
|
where T: Send + Sync + fmt::Display + fmt::Debug + 'static
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&self.cause, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ResponseError for InternalError<T>
|
||||||
|
where T: Send + Sync + fmt::Display + fmt::Debug + 'static
|
||||||
|
{
|
||||||
|
fn error_response(&self) -> HttpResponse {
|
||||||
|
HttpResponse::new(self.status, Body::Empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Responder for InternalError<T>
|
||||||
|
where T: Send + Sync + fmt::Display + fmt::Debug + 'static
|
||||||
|
{
|
||||||
|
type Item = HttpResponse;
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn respond_to(self, _: HttpRequest) -> Result<HttpResponse, Error> {
|
||||||
|
Err(self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper type that can wrap any error and generate *BAD REQUEST* response.
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn ErrorBadRequest<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::BAD_REQUEST)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *UNAUTHORIZED* response.
|
/// Helper type that can wrap any error and generate *UNAUTHORIZED* response.
|
||||||
pub struct ErrorUnauthorized<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorUnauthorized<T>, StatusCode::UNAUTHORIZED);
|
pub fn ErrorUnauthorized<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::UNAUTHORIZED)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *FORBIDDEN* response.
|
/// Helper type that can wrap any error and generate *FORBIDDEN* response.
|
||||||
pub struct ErrorForbidden<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorForbidden<T>, StatusCode::FORBIDDEN);
|
pub fn ErrorForbidden<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::FORBIDDEN)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *NOT FOUND* response.
|
/// Helper type that can wrap any error and generate *NOT FOUND* response.
|
||||||
pub struct ErrorNotFound<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorNotFound<T>, StatusCode::NOT_FOUND);
|
pub fn ErrorNotFound<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::NOT_FOUND)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *METHOD NOT ALLOWED* response.
|
/// Helper type that can wrap any error and generate *METHOD NOT ALLOWED* response.
|
||||||
pub struct ErrorMethodNotAllowed<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorMethodNotAllowed<T>, StatusCode::METHOD_NOT_ALLOWED);
|
pub fn ErrorMethodNotAllowed<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *REQUEST TIMEOUT* response.
|
/// Helper type that can wrap any error and generate *REQUEST TIMEOUT* response.
|
||||||
pub struct ErrorRequestTimeout<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorRequestTimeout<T>, StatusCode::REQUEST_TIMEOUT);
|
pub fn ErrorRequestTimeout<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::REQUEST_TIMEOUT)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *CONFLICT* response.
|
/// Helper type that can wrap any error and generate *CONFLICT* response.
|
||||||
pub struct ErrorConflict<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorConflict<T>, StatusCode::CONFLICT);
|
pub fn ErrorConflict<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::CONFLICT)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *GONE* response.
|
/// Helper type that can wrap any error and generate *GONE* response.
|
||||||
pub struct ErrorGone<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorGone<T>, StatusCode::GONE);
|
pub fn ErrorGone<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::GONE)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *PRECONDITION FAILED* response.
|
/// Helper type that can wrap any error and generate *PRECONDITION FAILED* response.
|
||||||
pub struct ErrorPreconditionFailed<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorPreconditionFailed<T>, StatusCode::PRECONDITION_FAILED);
|
pub fn ErrorPreconditionFailed<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::PRECONDITION_FAILED)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *EXPECTATION FAILED* response.
|
/// Helper type that can wrap any error and generate *EXPECTATION FAILED* response.
|
||||||
pub struct ErrorExpectationFailed<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorExpectationFailed<T>, StatusCode::EXPECTATION_FAILED);
|
pub fn ErrorExpectationFailed<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::EXPECTATION_FAILED)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Helper type that can wrap any error and generate *INTERNAL SERVER ERROR* response.
|
/// Helper type that can wrap any error and generate *INTERNAL SERVER ERROR* response.
|
||||||
pub struct ErrorInternalServerError<T>(pub T);
|
#[allow(non_snake_case)]
|
||||||
ERROR_WRAP!(ErrorInternalServerError<T>, StatusCode::INTERNAL_SERVER_ERROR);
|
pub fn ErrorInternalServerError<T>(err: T) -> InternalError<T> {
|
||||||
|
InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -6,7 +6,7 @@ use std::slice::Iter;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use error::{ResponseError, UriSegmentError, ErrorBadRequest};
|
use error::{ResponseError, UriSegmentError, InternalError, ErrorBadRequest};
|
||||||
|
|
||||||
|
|
||||||
/// A trait to abstract the idea of creating a new instance of a type from a path parameter.
|
/// A trait to abstract the idea of creating a new instance of a type from a path parameter.
|
||||||
@ -141,7 +141,7 @@ impl FromParam for PathBuf {
|
|||||||
macro_rules! FROM_STR {
|
macro_rules! FROM_STR {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
impl FromParam for $type {
|
impl FromParam for $type {
|
||||||
type Err = ErrorBadRequest<<$type as FromStr>::Err>;
|
type Err = InternalError<<$type as FromStr>::Err>;
|
||||||
|
|
||||||
fn from_param(val: &str) -> Result<Self, Self::Err> {
|
fn from_param(val: &str) -> Result<Self, Self::Err> {
|
||||||
<$type as FromStr>::from_str(val).map_err(ErrorBadRequest)
|
<$type as FromStr>::from_str(val).map_err(ErrorBadRequest)
|
||||||
|
Loading…
Reference in New Issue
Block a user