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