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}