use thiserror::Error;
pub type ProxyResult<T> = Result<T, ProxyError>;
#[derive(Error, Debug)]
pub enum ProxyError {
#[error("Configuration error: {0}")]
Config(String),
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("TLS error: {0}")]
Tls(String),
#[error("ACME error: {0}")]
Acme(String),
#[error("HTTP error: {0}")]
Http(String),
#[error("Upstream error: {0}")]
Upstream(String),
#[error("Health check error: {0}")]
HealthCheck(String),
#[error("Rate limit exceeded")]
RateLimitExceeded,
#[error("Route not found: {0}")]
RouteNotFound(String),
#[error("Backend not found: {0}")]
BackendNotFound(String),
#[error("No healthy backends available for upstream: {0}")]
NoHealthyBackends(String),
#[error("Invalid URL: {0}")]
InvalidUrl(#[from] url::ParseError),
#[error("TOML parsing error: {0}")]
Toml(#[from] toml::de::Error),
#[error("File watcher error: {0}")]
Notify(#[from] notify::Error),
#[error("Internal error: {0}")]
Internal(String),
#[error("Domain verification error: {0}")]
Verification(String),
#[error("Authentication error: {0}")]
Auth(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Quota exceeded: {0}")]
QuotaExceeded(String),
#[error("Conflict: {0}")]
Conflict(String),
#[error("Tenant suspended")]
TenantSuspended,
#[error("Not found: {0}")]
NotFound(String),
#[error("Forbidden: {0}")]
Forbidden(String),
}
impl ProxyError {
pub fn status_code(&self) -> http::StatusCode {
match self {
ProxyError::Config(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Database(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Io(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Tls(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Acme(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Http(_) => http::StatusCode::BAD_GATEWAY,
ProxyError::Upstream(_) => http::StatusCode::BAD_GATEWAY,
ProxyError::HealthCheck(_) => http::StatusCode::SERVICE_UNAVAILABLE,
ProxyError::RateLimitExceeded => http::StatusCode::TOO_MANY_REQUESTS,
ProxyError::RouteNotFound(_) => http::StatusCode::NOT_FOUND,
ProxyError::BackendNotFound(_) => http::StatusCode::NOT_FOUND,
ProxyError::NoHealthyBackends(_) => http::StatusCode::SERVICE_UNAVAILABLE,
ProxyError::InvalidUrl(_) => http::StatusCode::BAD_REQUEST,
ProxyError::Toml(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Notify(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Internal(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
ProxyError::Verification(_) => http::StatusCode::BAD_REQUEST,
ProxyError::Auth(_) => http::StatusCode::UNAUTHORIZED,
ProxyError::Validation(_) => http::StatusCode::BAD_REQUEST,
ProxyError::QuotaExceeded(_) => http::StatusCode::PAYMENT_REQUIRED,
ProxyError::Conflict(_) => http::StatusCode::CONFLICT,
ProxyError::TenantSuspended => http::StatusCode::FORBIDDEN,
ProxyError::NotFound(_) => http::StatusCode::NOT_FOUND,
ProxyError::Forbidden(_) => http::StatusCode::FORBIDDEN,
}
}
}