1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00

refactor helper error types

This commit is contained in:
Nikolay Kim 2018-01-20 21:11:46 -08:00
parent 552320bae2
commit 9180625dfd
7 changed files with 117 additions and 88 deletions

View File

@ -5,7 +5,7 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
workspace = "../.."
[dependencies]
env_logger = "0.4"
env_logger = "0.5"
actix = "0.4"
actix-web = { path = "../../" }

View File

@ -5,6 +5,6 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
workspace = "../.."
[dependencies]
env_logger = "0.4"
env_logger = "0.5"
actix = "0.4"
actix-web = { path = "../../" }

View File

@ -6,6 +6,6 @@ workspace = "../.."
[dependencies]
futures = "*"
env_logger = "0.4"
env_logger = "0.5"
actix = "0.4"
actix-web = { path = "../../" }

View File

@ -5,7 +5,7 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
workspace = "../.."
[dependencies]
env_logger = "0.4"
env_logger = "0.5"
actix = "0.4"
actix-web = { path = "../../" }
tera = "*"

View File

@ -9,6 +9,6 @@ name = "server"
path = "src/main.rs"
[dependencies]
env_logger = "0.4"
env_logger = "0.5"
actix = "^0.4.2"
actix-web = { path = "../../", features=["alpn"] }

View File

@ -68,8 +68,8 @@ impl fmt::Display for Error {
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.backtrace.is_none() {
fmt::Debug::fmt(&self.cause, f)
if let Some(bt) = self.cause.backtrace() {
write!(f, "{:?}\n\n{:?}", &self.cause, bt)
} else {
write!(f, "{:?}\n\n{:?}", &self.cause, self.backtrace.as_ref().unwrap())
}
@ -495,52 +495,7 @@ impl From<UrlParseError> for UrlGenerationError {
}
}
macro_rules! ERROR_WRAP {
($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.
/// Helper type that can wrap any error and generate custom 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.
@ -556,59 +511,133 @@ macro_rules! ERROR_WRAP {
/// }
/// # fn main() {}
/// ```
#[derive(Debug)]
pub struct ErrorBadRequest<T>(pub T);
ERROR_WRAP!(ErrorBadRequest<T>, StatusCode::BAD_REQUEST);
pub struct InternalError<T> {
cause: T,
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.
pub struct ErrorUnauthorized<T>(pub T);
ERROR_WRAP!(ErrorUnauthorized<T>, StatusCode::UNAUTHORIZED);
#[allow(non_snake_case)]
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.
pub struct ErrorForbidden<T>(pub T);
ERROR_WRAP!(ErrorForbidden<T>, StatusCode::FORBIDDEN);
#[allow(non_snake_case)]
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.
pub struct ErrorNotFound<T>(pub T);
ERROR_WRAP!(ErrorNotFound<T>, StatusCode::NOT_FOUND);
#[allow(non_snake_case)]
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.
pub struct ErrorMethodNotAllowed<T>(pub T);
ERROR_WRAP!(ErrorMethodNotAllowed<T>, StatusCode::METHOD_NOT_ALLOWED);
#[allow(non_snake_case)]
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.
pub struct ErrorRequestTimeout<T>(pub T);
ERROR_WRAP!(ErrorRequestTimeout<T>, StatusCode::REQUEST_TIMEOUT);
#[allow(non_snake_case)]
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.
pub struct ErrorConflict<T>(pub T);
ERROR_WRAP!(ErrorConflict<T>, StatusCode::CONFLICT);
#[allow(non_snake_case)]
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.
pub struct ErrorGone<T>(pub T);
ERROR_WRAP!(ErrorGone<T>, StatusCode::GONE);
#[allow(non_snake_case)]
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.
pub struct ErrorPreconditionFailed<T>(pub T);
ERROR_WRAP!(ErrorPreconditionFailed<T>, StatusCode::PRECONDITION_FAILED);
#[allow(non_snake_case)]
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.
pub struct ErrorExpectationFailed<T>(pub T);
ERROR_WRAP!(ErrorExpectationFailed<T>, StatusCode::EXPECTATION_FAILED);
#[allow(non_snake_case)]
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.
pub struct ErrorInternalServerError<T>(pub T);
ERROR_WRAP!(ErrorInternalServerError<T>, StatusCode::INTERNAL_SERVER_ERROR);
#[allow(non_snake_case)]
pub fn ErrorInternalServerError<T>(err: T) -> InternalError<T> {
InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR)
}
#[cfg(test)]
mod tests {

View File

@ -6,7 +6,7 @@ use std::slice::Iter;
use std::borrow::Cow;
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.
@ -141,7 +141,7 @@ impl FromParam for PathBuf {
macro_rules! FROM_STR {
($type:ty) => {
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> {
<$type as FromStr>::from_str(val).map_err(ErrorBadRequest)