1use thiserror::Error;
5
6#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum GatewayError {
12 #[error("failed to bind {0}: {1}")]
17 Bind(String, #[source] std::io::Error),
18
19 #[error("server error: {0}")]
23 Server(#[source] std::io::Error),
24
25 #[error(
32 "refusing to start gateway: no auth_token configured — every request would be \
33 unauthenticated. Set [gateway] auth_token or store one at vault key ZEPH_GATEWAY_TOKEN \
34 (`zeph vault set ZEPH_GATEWAY_TOKEN <token>`)"
35 )]
36 MissingAuthToken,
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[test]
44 fn bind_error_exposes_io_error_as_source() {
45 let io_err = std::io::Error::new(std::io::ErrorKind::AddrInUse, "address in use");
46 let err = GatewayError::Bind("127.0.0.1:8080".to_string(), io_err);
47
48 let source = std::error::Error::source(&err).expect("Bind must expose a source");
49 let downcast = source
50 .downcast_ref::<std::io::Error>()
51 .expect("source must downcast to std::io::Error");
52 assert_eq!(downcast.kind(), std::io::ErrorKind::AddrInUse);
53
54 assert_eq!(
55 err.to_string(),
56 "failed to bind 127.0.0.1:8080: address in use"
57 );
58 }
59
60 #[test]
61 fn server_error_exposes_io_error_as_source() {
62 let io_err = std::io::Error::new(std::io::ErrorKind::BrokenPipe, "broken pipe");
63 let err = GatewayError::Server(io_err);
64
65 let source = std::error::Error::source(&err).expect("Server must expose a source");
66 let downcast = source
67 .downcast_ref::<std::io::Error>()
68 .expect("source must downcast to std::io::Error");
69 assert_eq!(downcast.kind(), std::io::ErrorKind::BrokenPipe);
70
71 assert_eq!(err.to_string(), "server error: broken pipe");
72 }
73}