1use thiserror::Error;
4
5pub type ProxyResult<T> = Result<T, ProxyError>;
7
8#[derive(Error, Debug)]
10pub enum ProxyError {
11 #[error("Configuration error: {0}")]
13 Config(String),
14
15 #[error("Database error: {0}")]
17 Database(#[from] sqlx::Error),
18
19 #[error("IO error: {0}")]
21 Io(#[from] std::io::Error),
22
23 #[error("TLS error: {0}")]
25 Tls(String),
26
27 #[error("ACME error: {0}")]
29 Acme(String),
30
31 #[error("HTTP error: {0}")]
33 Http(String),
34
35 #[error("Upstream error: {0}")]
37 Upstream(String),
38
39 #[error("Health check error: {0}")]
41 HealthCheck(String),
42
43 #[error("Rate limit exceeded")]
45 RateLimitExceeded,
46
47 #[error("Route not found: {0}")]
49 RouteNotFound(String),
50
51 #[error("Backend not found: {0}")]
53 BackendNotFound(String),
54
55 #[error("No healthy backends available for upstream: {0}")]
57 NoHealthyBackends(String),
58
59 #[error("Invalid URL: {0}")]
61 InvalidUrl(#[from] url::ParseError),
62
63 #[error("TOML parsing error: {0}")]
65 Toml(#[from] toml::de::Error),
66
67 #[error("Internal error: {0}")]
69 Internal(String),
70
71 #[error("Domain verification error: {0}")]
74 Verification(String),
75
76 #[error("Authentication error: {0}")]
78 Auth(String),
79
80 #[error("Validation error: {0}")]
82 Validation(String),
83
84 #[error("Quota exceeded: {0}")]
86 QuotaExceeded(String),
87
88 #[error("Conflict: {0}")]
90 Conflict(String),
91
92 #[error("Tenant suspended")]
94 TenantSuspended,
95
96 #[error("Not found: {0}")]
98 NotFound(String),
99
100 #[error("Forbidden: {0}")]
102 Forbidden(String),
103}
104
105impl ProxyError {
106 pub fn status_code(&self) -> http::StatusCode {
108 match self {
109 ProxyError::Config(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
110 ProxyError::Database(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
111 ProxyError::Io(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
112 ProxyError::Tls(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
113 ProxyError::Acme(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
114 ProxyError::Http(_) => http::StatusCode::BAD_GATEWAY,
115 ProxyError::Upstream(_) => http::StatusCode::BAD_GATEWAY,
116 ProxyError::HealthCheck(_) => http::StatusCode::SERVICE_UNAVAILABLE,
117 ProxyError::RateLimitExceeded => http::StatusCode::TOO_MANY_REQUESTS,
118 ProxyError::RouteNotFound(_) => http::StatusCode::NOT_FOUND,
119 ProxyError::BackendNotFound(_) => http::StatusCode::NOT_FOUND,
120 ProxyError::NoHealthyBackends(_) => http::StatusCode::SERVICE_UNAVAILABLE,
121 ProxyError::InvalidUrl(_) => http::StatusCode::BAD_REQUEST,
122 ProxyError::Toml(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
123 ProxyError::Internal(_) => http::StatusCode::INTERNAL_SERVER_ERROR,
124 ProxyError::Verification(_) => http::StatusCode::BAD_REQUEST,
125 ProxyError::Auth(_) => http::StatusCode::UNAUTHORIZED,
126 ProxyError::Validation(_) => http::StatusCode::BAD_REQUEST,
127 ProxyError::QuotaExceeded(_) => http::StatusCode::PAYMENT_REQUIRED,
128 ProxyError::Conflict(_) => http::StatusCode::CONFLICT,
129 ProxyError::TenantSuspended => http::StatusCode::FORBIDDEN,
130 ProxyError::NotFound(_) => http::StatusCode::NOT_FOUND,
131 ProxyError::Forbidden(_) => http::StatusCode::FORBIDDEN,
132 }
133 }
134}