hyper_middleware/error/
mod.rs

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