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}