1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum ApiError {
5 #[error("BadRequestError: Bad request - {message}")]
6 BadRequestError {
7 message: String,
8 code: Option<String>,
9 error: Option<String>,
10 },
11 #[error("UnauthorizedError: Authentication failed - {message}")]
12 UnauthorizedError {
13 message: String,
14 code: Option<String>,
15 error: Option<String>,
16 },
17 #[error("NotFoundError: Resource not found - {message}")]
18 NotFoundError {
19 message: String,
20 code: Option<String>,
21 error: Option<String>,
22 },
23 #[error("ConflictError: Conflict - {message}")]
24 ConflictError {
25 message: String,
26 code: Option<String>,
27 error: Option<String>,
28 },
29 #[error("TooManyRequestsError: Rate limit exceeded - {message}")]
30 TooManyRequestsError {
31 message: String,
32 code: Option<String>,
33 error: Option<String>,
34 },
35 #[error("InternalServerError: Internal server error - {message}")]
36 InternalServerError {
37 message: String,
38 code: Option<String>,
39 error: Option<String>,
40 },
41 #[error("BadGatewayError: {message}")]
42 BadGatewayError {
43 message: String,
44 code: Option<String>,
45 error: Option<String>,
46 },
47 #[error("ServiceUnavailableError: {message}")]
48 ServiceUnavailableError {
49 message: String,
50 code: Option<String>,
51 error: Option<String>,
52 },
53 #[error("HTTP error {status}: {message}")]
54 Http { status: u16, message: String },
55 #[error("Network error: {0}")]
56 Network(reqwest::Error),
57 #[error("Request executor error: {0}")]
58 Executor(Box<dyn std::error::Error + Send + Sync>),
59 #[error("Serialization error: {0}")]
60 Serialization(serde_json::Error),
61 #[error("Configuration error: {0}")]
62 Configuration(String),
63 #[error("Invalid header value")]
64 InvalidHeader,
65 #[error("Could not clone request for retry")]
66 RequestClone,
67 #[error("SSE stream terminated")]
68 StreamTerminated,
69 #[error("SSE stream timed out waiting for next event")]
70 StreamTimeout,
71 #[error("SSE parse error: {0}")]
72 SseParseError(String),
73}
74
75impl ApiError {
76 pub fn from_response(status_code: u16, body: Option<&str>) -> Self {
77 match status_code {
78 400 => {
79 if let Some(body_str) = body {
81 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
82 return Self::BadRequestError {
83 message: parsed
84 .get("message")
85 .and_then(|v| v.as_str())
86 .unwrap_or("Unknown error")
87 .to_string(),
88 code: parsed
89 .get("code")
90 .and_then(|v| v.as_str().map(|s| s.to_string())),
91 error: parsed
92 .get("error")
93 .and_then(|v| v.as_str().map(|s| s.to_string())),
94 };
95 }
96 }
97 return Self::BadRequestError {
98 message: body.unwrap_or("Unknown error").to_string(),
99 code: None,
100 error: None,
101 };
102 }
103 401 => {
104 if let Some(body_str) = body {
106 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
107 return Self::UnauthorizedError {
108 message: parsed
109 .get("message")
110 .and_then(|v| v.as_str())
111 .unwrap_or("Unknown error")
112 .to_string(),
113 code: parsed
114 .get("code")
115 .and_then(|v| v.as_str().map(|s| s.to_string())),
116 error: parsed
117 .get("error")
118 .and_then(|v| v.as_str().map(|s| s.to_string())),
119 };
120 }
121 }
122 return Self::UnauthorizedError {
123 message: body.unwrap_or("Unknown error").to_string(),
124 code: None,
125 error: None,
126 };
127 }
128 404 => {
129 if let Some(body_str) = body {
131 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
132 return Self::NotFoundError {
133 message: parsed
134 .get("message")
135 .and_then(|v| v.as_str())
136 .unwrap_or("Unknown error")
137 .to_string(),
138 code: parsed
139 .get("code")
140 .and_then(|v| v.as_str().map(|s| s.to_string())),
141 error: parsed
142 .get("error")
143 .and_then(|v| v.as_str().map(|s| s.to_string())),
144 };
145 }
146 }
147 return Self::NotFoundError {
148 message: body.unwrap_or("Unknown error").to_string(),
149 code: None,
150 error: None,
151 };
152 }
153 409 => {
154 if let Some(body_str) = body {
156 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
157 return Self::ConflictError {
158 message: parsed
159 .get("message")
160 .and_then(|v| v.as_str())
161 .unwrap_or("Unknown error")
162 .to_string(),
163 code: parsed
164 .get("code")
165 .and_then(|v| v.as_str().map(|s| s.to_string())),
166 error: parsed
167 .get("error")
168 .and_then(|v| v.as_str().map(|s| s.to_string())),
169 };
170 }
171 }
172 return Self::ConflictError {
173 message: body.unwrap_or("Unknown error").to_string(),
174 code: None,
175 error: None,
176 };
177 }
178 429 => {
179 if let Some(body_str) = body {
181 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
182 return Self::TooManyRequestsError {
183 message: parsed
184 .get("message")
185 .and_then(|v| v.as_str())
186 .unwrap_or("Unknown error")
187 .to_string(),
188 code: parsed
189 .get("code")
190 .and_then(|v| v.as_str().map(|s| s.to_string())),
191 error: parsed
192 .get("error")
193 .and_then(|v| v.as_str().map(|s| s.to_string())),
194 };
195 }
196 }
197 return Self::TooManyRequestsError {
198 message: body.unwrap_or("Unknown error").to_string(),
199 code: None,
200 error: None,
201 };
202 }
203 500 => {
204 if let Some(body_str) = body {
206 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
207 return Self::InternalServerError {
208 message: parsed
209 .get("message")
210 .and_then(|v| v.as_str())
211 .unwrap_or("Unknown error")
212 .to_string(),
213 code: parsed
214 .get("code")
215 .and_then(|v| v.as_str().map(|s| s.to_string())),
216 error: parsed
217 .get("error")
218 .and_then(|v| v.as_str().map(|s| s.to_string())),
219 };
220 }
221 }
222 return Self::InternalServerError {
223 message: body.unwrap_or("Unknown error").to_string(),
224 code: None,
225 error: None,
226 };
227 }
228 502 => {
229 if let Some(body_str) = body {
231 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
232 return Self::BadGatewayError {
233 message: parsed
234 .get("message")
235 .and_then(|v| v.as_str())
236 .unwrap_or("Unknown error")
237 .to_string(),
238 code: parsed
239 .get("code")
240 .and_then(|v| v.as_str().map(|s| s.to_string())),
241 error: parsed
242 .get("error")
243 .and_then(|v| v.as_str().map(|s| s.to_string())),
244 };
245 }
246 }
247 return Self::BadGatewayError {
248 message: body.unwrap_or("Unknown error").to_string(),
249 code: None,
250 error: None,
251 };
252 }
253 503 => {
254 if let Some(body_str) = body {
256 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(body_str) {
257 return Self::ServiceUnavailableError {
258 message: parsed
259 .get("message")
260 .and_then(|v| v.as_str())
261 .unwrap_or("Unknown error")
262 .to_string(),
263 code: parsed
264 .get("code")
265 .and_then(|v| v.as_str().map(|s| s.to_string())),
266 error: parsed
267 .get("error")
268 .and_then(|v| v.as_str().map(|s| s.to_string())),
269 };
270 }
271 }
272 return Self::ServiceUnavailableError {
273 message: body.unwrap_or("Unknown error").to_string(),
274 code: None,
275 error: None,
276 };
277 }
278 _ => Self::Http {
279 status: status_code,
280 message: body.unwrap_or("Unknown error").to_string(),
281 },
282 }
283 }
284}
285
286#[derive(Debug)]
288pub struct BuildError {
289 field: &'static str,
290}
291
292impl BuildError {
293 pub fn missing_field(field: &'static str) -> Self {
294 Self { field }
295 }
296}
297
298impl std::fmt::Display for BuildError {
299 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
300 write!(f, "`{}` was not set but is required", self.field)
301 }
302}
303
304impl std::error::Error for BuildError {}