1use std::convert::Infallible;
2use std::io::{self, ErrorKind};
3use std::error::Error;
4
5use crate::reqres::StatusCode;
6
7#[derive(Debug, Clone, Copy)]
11pub enum HttpErrorType {
12 Fatal,
14 Hidden,
16 User,
18}
19
20pub trait HttpError: Error + Send + 'static {
24 fn name(&self) -> &'static str {
26 std::any::type_name::<Self>().split("::").last().unwrap()
28 }
29
30 fn error_type(&self) -> HttpErrorType {
32 HttpErrorType::User
33 }
34
35 fn http_description(&self) -> String {
37 self.to_string()
38 }
39
40 fn status_code(&self) -> StatusCode {
42 StatusCode::INTERNAL_SERVER_ERROR
43 }
44}
45
46impl<E: HttpError> From<E> for Box<dyn HttpError> {
47 fn from(value: E) -> Box<dyn HttpError> {
48 Box::new(value)
49 }
50}
51
52fn is_net(kind: ErrorKind) -> bool {
53 matches!(kind, ErrorKind::ConnectionRefused
54 | ErrorKind::ConnectionReset
55 | ErrorKind::HostUnreachable
56 | ErrorKind::NetworkUnreachable
57 | ErrorKind::ConnectionAborted
58 | ErrorKind::NotConnected
59 | ErrorKind::AddrInUse
60 | ErrorKind::AddrNotAvailable
61 | ErrorKind::NetworkDown
62 | ErrorKind::BrokenPipe
63 | ErrorKind::TimedOut)
64}
65
66impl HttpError for io::Error {
67 fn name(&self) -> &'static str {
68 "io::Error"
69 }
70
71 fn error_type(&self) -> HttpErrorType {
72 if is_net(self.kind()) {
73 HttpErrorType::Fatal
74 } else {
75 HttpErrorType::User
76 }
77 }
78
79 fn http_description(&self) -> String {
80 match self.kind() {
81 ErrorKind::NotFound | ErrorKind::NotADirectory => "The requested resource was not found on this server".to_string(),
82 ErrorKind::PermissionDenied => "Access denied".to_string(),
83 _ => self.to_string(),
84 }
85 }
86
87 fn status_code(&self) -> StatusCode {
88 match self.kind() {
89 ErrorKind::NotFound | ErrorKind::NotADirectory => StatusCode::NOT_FOUND,
90 ErrorKind::PermissionDenied => StatusCode::FORBIDDEN,
91 _ => StatusCode::INTERNAL_SERVER_ERROR,
92 }
93 }
94}
95
96impl HttpError for Infallible {}
97
98impl HttpError for tokio::task::JoinError {
99 fn error_type(&self) -> HttpErrorType {
100 HttpErrorType::Hidden
102 }
103}
104
105impl HttpError for std::string::FromUtf8Error {}