Skip to main content

cloudiful_server/core/
error.rs

1use std::{fmt, path::PathBuf};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
4pub enum ServerConfigError {
5    MissingListenAddr,
6    MissingCorsOrigins,
7    MissingCorsMethods,
8    InvalidCorsOrigin(String),
9    InvalidCorsMethod(String),
10    MissingTlsCertPath,
11    MissingTlsKeyPath,
12}
13
14impl fmt::Display for ServerConfigError {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        match self {
17            Self::MissingListenAddr => write!(f, "listen_addr must not be empty"),
18            Self::MissingCorsOrigins => {
19                write!(
20                    f,
21                    "restricted CORS configuration requires at least one origin"
22                )
23            }
24            Self::MissingCorsMethods => {
25                write!(
26                    f,
27                    "restricted CORS configuration requires at least one method"
28                )
29            }
30            Self::InvalidCorsOrigin(origin) => {
31                write!(f, "restricted CORS origin is invalid: {origin}")
32            }
33            Self::InvalidCorsMethod(method) => {
34                write!(f, "restricted CORS method is invalid: {method}")
35            }
36            Self::MissingTlsCertPath => write!(f, "TLS configuration requires cert_path"),
37            Self::MissingTlsKeyPath => write!(f, "TLS configuration requires cert_key_path"),
38        }
39    }
40}
41
42impl std::error::Error for ServerConfigError {}
43
44#[derive(Debug)]
45pub enum TlsConfigLoadError {
46    OpenCertificate {
47        path: PathBuf,
48        source: std::io::Error,
49    },
50    ReadCertificates {
51        path: PathBuf,
52        source: std::io::Error,
53    },
54    OpenPrivateKey {
55        path: PathBuf,
56        source: std::io::Error,
57    },
58    OpenClientCa {
59        path: PathBuf,
60        source: std::io::Error,
61    },
62    ReadClientCa {
63        path: PathBuf,
64        source: std::io::Error,
65    },
66    ReadPrivateKey {
67        path: PathBuf,
68        source: std::io::Error,
69    },
70    InvalidClientCa {
71        path: PathBuf,
72        source: rustls::Error,
73    },
74    MissingPrivateKey {
75        path: PathBuf,
76    },
77    InvalidConfig {
78        source: rustls::Error,
79    },
80}
81
82impl fmt::Display for TlsConfigLoadError {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        match self {
85            Self::OpenCertificate { path, source } => {
86                write!(
87                    f,
88                    "failed to open TLS certificate at {}: {source}",
89                    path.display()
90                )
91            }
92            Self::ReadCertificates { path, source } => {
93                write!(
94                    f,
95                    "failed to read TLS certificates from {}: {source}",
96                    path.display()
97                )
98            }
99            Self::OpenPrivateKey { path, source } => {
100                write!(
101                    f,
102                    "failed to open TLS private key at {}: {source}",
103                    path.display()
104                )
105            }
106            Self::OpenClientCa { path, source } => {
107                write!(
108                    f,
109                    "failed to open TLS client CA at {}: {source}",
110                    path.display()
111                )
112            }
113            Self::ReadClientCa { path, source } => {
114                write!(
115                    f,
116                    "failed to read TLS client CA certificates from {}: {source}",
117                    path.display()
118                )
119            }
120            Self::ReadPrivateKey { path, source } => {
121                write!(
122                    f,
123                    "failed to read TLS private key from {}: {source}",
124                    path.display()
125                )
126            }
127            Self::InvalidClientCa { path, source } => {
128                write!(
129                    f,
130                    "failed to build TLS client certificate verifier from {}: {source}",
131                    path.display()
132                )
133            }
134            Self::MissingPrivateKey { path } => {
135                write!(f, "no TLS private key found in {}", path.display())
136            }
137            Self::InvalidConfig { source } => {
138                write!(f, "failed to build TLS server configuration: {source}")
139            }
140        }
141    }
142}
143
144impl std::error::Error for TlsConfigLoadError {
145    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
146        match self {
147            Self::OpenCertificate { source, .. }
148            | Self::ReadCertificates { source, .. }
149            | Self::OpenPrivateKey { source, .. }
150            | Self::OpenClientCa { source, .. }
151            | Self::ReadClientCa { source, .. }
152            | Self::ReadPrivateKey { source, .. } => Some(source),
153            Self::InvalidConfig { source } => Some(source),
154            Self::InvalidClientCa { source, .. } => Some(source),
155            Self::MissingPrivateKey { .. } => None,
156        }
157    }
158}
159
160#[derive(Debug)]
161pub enum ServerError {
162    Config(ServerConfigError),
163    Io(std::io::Error),
164    Tls(TlsConfigLoadError),
165}
166
167impl fmt::Display for ServerError {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        match self {
170            Self::Config(err) => err.fmt(f),
171            Self::Io(err) => err.fmt(f),
172            Self::Tls(err) => err.fmt(f),
173        }
174    }
175}
176
177impl std::error::Error for ServerError {
178    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
179        match self {
180            Self::Config(err) => Some(err),
181            Self::Io(err) => Some(err),
182            Self::Tls(err) => Some(err),
183        }
184    }
185}
186
187impl From<ServerConfigError> for ServerError {
188    fn from(value: ServerConfigError) -> Self {
189        Self::Config(value)
190    }
191}
192
193impl From<std::io::Error> for ServerError {
194    fn from(value: std::io::Error) -> Self {
195        Self::Io(value)
196    }
197}