1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//! The custom error module.
//!
//! This module provides a custom [`Error`][`super::Error`] type with HTTP Status functionality as well as useful macros.
//! The `Error` type implements other several common error types
//! to ease conversions while consuming the input value via the [`From`] trait.
//!
//! Additionally, when used in HTTP contexts, the `Error` type can be associated to an [HTTP Status Code][`hyper::StatusCode`].
//! via the [`Error::with_status`][`super::Error::with_status`] method.
//!
//! a. Construct an [`Error`][`super::Error`] from [`hyper::Error`], [`std::io::Error`], [`anyhow::Error`] or an string.
//!
//! ```rust
//! use hyper_middleware::error
//!
//! let err = Error::from("some error type or string");
//! // Or using a shortcut macro
//! let err = error!("some error type or string");
//! ```
//!
//! b. Construct an [`Error`][`super::Error`] with an associated [HTTP Status Code][`hyper::StatusCode`].
//!
//! ```rust
//! use hyper::StatusCode;
//! use hyper_middleware::error
//!
//! let err = error!("user or password does not match").with_status(StatusCode::UNAUTHORIZED);
//! // Or using a shortcut macro
//! let err = http_error_unauthorized!("user or password does not match");
//! ```
//!
use hyper::StatusCode;
use std::fmt;
use thiserror::Error as ThisError;
pub mod macros;
pub type Result<T = (), E = Error> = anyhow::Result<T, E>;
pub use anyhow::Context;
/// Represents an HTTP Error.
#[derive(ThisError, Debug)]
pub struct Error {
source: anyhow::Error,
status: Option<StatusCode>,
}
impl Error {
/// Returns the underlying error.
pub fn source(self) -> anyhow::Error {
self.source
}
/// Returns the HTTP `StatusCode` associated with the underlying error.
pub fn status(&self) -> Option<StatusCode> {
self.status
}
/// Adds/updates the current HTTP Status Code.
pub fn with_status(mut self, status: StatusCode) -> Self {
self.status = Some(status);
self
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.source, f)
}
}
impl From<hyper::Error> for Error {
/// Converts a [`hyper::Error`] type into an HTTP [`Error`].
fn from(source: hyper::Error) -> Self {
Self {
source: anyhow::anyhow!(source),
status: None,
}
}
}
impl From<std::io::Error> for Error {
/// Converts an error type that implements [`std::io::Error`] into an HTTP [`Error`].
fn from(source: std::io::Error) -> Self {
Self {
source: anyhow::anyhow!(source),
status: None,
}
}
}
impl From<anyhow::Error> for Error {
/// Converts whatever error type that implements [`std::error::Error`] into an HTTP [`Error`].
fn from(source: anyhow::Error) -> Self {
Self {
source,
status: None,
}
}
}
impl From<&str> for Error {
/// Converts a string error into an HTTP [`Error`].
fn from(source: &str) -> Self {
Self {
source: anyhow::anyhow!(source.to_owned()),
status: None,
}
}
}