use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum GatewayError {
#[error("failed to bind {0}: {1}")]
Bind(String, #[source] std::io::Error),
#[error("server error: {0}")]
Server(#[source] std::io::Error),
#[error(
"refusing to start gateway: no auth_token configured — every request would be \
unauthenticated. Set [gateway] auth_token or store one at vault key ZEPH_GATEWAY_TOKEN \
(`zeph vault set ZEPH_GATEWAY_TOKEN <token>`)"
)]
MissingAuthToken,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bind_error_exposes_io_error_as_source() {
let io_err = std::io::Error::new(std::io::ErrorKind::AddrInUse, "address in use");
let err = GatewayError::Bind("127.0.0.1:8080".to_string(), io_err);
let source = std::error::Error::source(&err).expect("Bind must expose a source");
let downcast = source
.downcast_ref::<std::io::Error>()
.expect("source must downcast to std::io::Error");
assert_eq!(downcast.kind(), std::io::ErrorKind::AddrInUse);
assert_eq!(
err.to_string(),
"failed to bind 127.0.0.1:8080: address in use"
);
}
#[test]
fn server_error_exposes_io_error_as_source() {
let io_err = std::io::Error::new(std::io::ErrorKind::BrokenPipe, "broken pipe");
let err = GatewayError::Server(io_err);
let source = std::error::Error::source(&err).expect("Server must expose a source");
let downcast = source
.downcast_ref::<std::io::Error>()
.expect("source must downcast to std::io::Error");
assert_eq!(downcast.kind(), std::io::ErrorKind::BrokenPipe);
assert_eq!(err.to_string(), "server error: broken pipe");
}
}