1mod any_http_error;
2pub mod error;
3pub mod option_ext;
4mod reason;
5pub mod result_ext;
6
7use std::error::Error;
8use std::fmt;
9
10pub use any_http_error::AnyHttpError;
11pub use http::StatusCode;
12use http::{HeaderName, HeaderValue};
13pub use option_ext::OptionExt;
14pub use reason::Reason;
15pub use result_ext::ResultExt;
16
17pub trait HttpError: Error {
18 fn status_code(&self) -> StatusCode;
19
20 fn reason(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 if let Some(reason) = self.status_code().canonical_reason() {
22 f.write_str(reason)?;
23 }
24 Ok(())
25 }
26
27 fn headers(&self) -> Option<Vec<(HeaderName, HeaderValue)>> {
28 None
29 }
30
31 #[cfg(feature = "tracing")]
32 fn span(&self) -> Option<&tracing::Span> {
33 None
34 }
35}
36
37impl<E> HttpError for Box<E>
38where
39 E: HttpError,
40{
41 fn status_code(&self) -> StatusCode {
42 HttpError::status_code(&**self)
43 }
44
45 fn reason(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 HttpError::reason(&**self, f)
47 }
48
49 fn headers(&self) -> Option<Vec<(HeaderName, HeaderValue)>> {
50 HttpError::headers(&**self)
51 }
52
53 #[cfg(feature = "tracing")]
54 fn span(&self) -> Option<&tracing::Span> {
55 HttpError::span(&**self)
56 }
57}
58
59impl HttpError for &dyn HttpError {
60 fn status_code(&self) -> StatusCode {
61 HttpError::status_code(&**self)
62 }
63
64 fn reason(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 HttpError::reason(&**self, f)
66 }
67
68 fn headers(&self) -> Option<Vec<(HeaderName, HeaderValue)>> {
69 HttpError::headers(&**self)
70 }
71
72 #[cfg(feature = "tracing")]
73 fn span(&self) -> Option<&tracing::Span> {
74 HttpError::span(&**self)
75 }
76}
77
78impl<E> From<E> for Box<dyn HttpError>
79where
80 E: HttpError + 'static,
81{
82 fn from(err: E) -> Self {
83 Box::new(err)
84 }
85}