1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum Error {
5 #[error("authentication failed (status {status})")]
6 AuthenticationError { status: u16, message: Option<String>, request_id: Option<String> },
7
8 #[error("rate limited (status {status})")]
9 RateLimitError {
10 status: u16,
11 message: Option<String>,
12 retry_after_seconds: Option<u64>,
13 request_id: Option<String>,
14 },
15
16 #[error("validation failed (status {status})")]
17 ValidationError { status: u16, message: Option<String>, details: Option<serde_json::Value>, request_id: Option<String> },
18
19 #[error("resource not found (status {status})")]
20 NotFound { status: u16, message: Option<String>, request_id: Option<String> },
21
22 #[error("server error (status {status})")]
23 ServerError { status: u16, message: Option<String>, request_id: Option<String> },
24
25 #[error("api error (status {status})")]
26 ApiError {
27 status: u16,
28 code: Option<String>,
29 message: Option<String>,
30 details: Option<serde_json::Value>,
31 request_id: Option<String>,
32 },
33
34 #[error("invalid header `{name}`")]
35 InvalidHeader { name: String },
36
37 #[error(transparent)]
38 Transport(#[from] reqwest::Error),
39
40 #[error(transparent)]
41 Json(#[from] serde_json::Error),
42
43 #[error(transparent)]
44 Url(#[from] url::ParseError),
45}
46
47impl Error {
48 pub fn status(&self) -> Option<u16> {
49 use Error::*;
50 match self {
51 AuthenticationError { status, .. }
52 | RateLimitError { status, .. }
53 | ValidationError { status, .. }
54 | NotFound { status, .. }
55 | ServerError { status, .. }
56 | ApiError { status, .. } => Some(*status),
57 _ => None,
58 }
59 }
60
61 pub fn request_id(&self) -> Option<&str> {
62 use Error::*;
63 match self {
64 AuthenticationError { request_id, .. }
65 | RateLimitError { request_id, .. }
66 | ValidationError { request_id, .. }
67 | NotFound { request_id, .. }
68 | ServerError { request_id, .. }
69 | ApiError { request_id, .. } => request_id.as_deref(),
70 _ => None,
71 }
72 }
73}
74
75#[derive(Debug, serde::Deserialize)]
76pub struct ApiErrorBody {
77 pub code: Option<String>,
78 pub message: Option<String>,
79 pub details: Option<serde_json::Value>,
80}