Skip to main content

uapi_sdk_rust/
errors.rs

1use thiserror::Error;
2
3#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
4pub struct RateLimitPolicyEntry {
5    pub name: String,
6    pub quota: Option<i64>,
7    pub unit: Option<String>,
8    pub window_seconds: Option<u64>,
9}
10
11#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
12pub struct RateLimitStateEntry {
13    pub name: String,
14    pub remaining: Option<i64>,
15    pub unit: Option<String>,
16    pub reset_after_seconds: Option<u64>,
17}
18
19#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
20pub struct ResponseMeta {
21    pub request_id: Option<String>,
22    pub retry_after_raw: Option<String>,
23    pub retry_after_seconds: Option<u64>,
24    pub debit_status: Option<String>,
25    pub credits_requested: Option<i64>,
26    pub credits_charged: Option<i64>,
27    pub credits_pricing: Option<String>,
28    pub active_quota_buckets: Option<u64>,
29    pub stop_on_empty: Option<bool>,
30    pub rate_limit_policy_raw: Option<String>,
31    pub rate_limit_raw: Option<String>,
32    pub rate_limit_policies: std::collections::BTreeMap<String, RateLimitPolicyEntry>,
33    pub rate_limits: std::collections::BTreeMap<String, RateLimitStateEntry>,
34    pub balance_limit_cents: Option<i64>,
35    pub balance_remaining_cents: Option<i64>,
36    pub quota_limit_credits: Option<i64>,
37    pub quota_remaining_credits: Option<i64>,
38    pub visitor_quota_limit_credits: Option<i64>,
39    pub visitor_quota_remaining_credits: Option<i64>,
40    pub billing_key_rate_limit: Option<i64>,
41    pub billing_key_rate_remaining: Option<i64>,
42    pub billing_key_rate_unit: Option<String>,
43    pub billing_key_rate_window_seconds: Option<u64>,
44    pub billing_key_rate_reset_after_seconds: Option<u64>,
45    pub billing_ip_rate_limit: Option<i64>,
46    pub billing_ip_rate_remaining: Option<i64>,
47    pub billing_ip_rate_unit: Option<String>,
48    pub billing_ip_rate_window_seconds: Option<u64>,
49    pub billing_ip_rate_reset_after_seconds: Option<u64>,
50    pub visitor_rate_limit: Option<i64>,
51    pub visitor_rate_remaining: Option<i64>,
52    pub visitor_rate_unit: Option<String>,
53    pub visitor_rate_window_seconds: Option<u64>,
54    pub visitor_rate_reset_after_seconds: Option<u64>,
55    pub raw_headers: std::collections::BTreeMap<String, String>,
56}
57
58#[derive(Debug, Error)]
59pub enum Error {
60    #[error("authentication failed (status {status})")]
61    AuthenticationError {
62        status: u16,
63        message: Option<String>,
64        request_id: Option<String>,
65        meta: Option<ResponseMeta>,
66    },
67
68    #[error("rate limited (status {status})")]
69    RateLimitError {
70        status: u16,
71        message: Option<String>,
72        retry_after_seconds: Option<u64>,
73        request_id: Option<String>,
74        meta: Option<ResponseMeta>,
75    },
76
77    #[error("insufficient credits (status {status})")]
78    InsufficientCredits {
79        status: u16,
80        message: Option<String>,
81        details: Option<serde_json::Value>,
82        request_id: Option<String>,
83        meta: Option<ResponseMeta>,
84    },
85
86    #[error("visitor monthly quota exhausted (status {status})")]
87    VisitorMonthlyQuotaExhausted {
88        status: u16,
89        message: Option<String>,
90        details: Option<serde_json::Value>,
91        request_id: Option<String>,
92        meta: Option<ResponseMeta>,
93    },
94
95    #[error("validation failed (status {status})")]
96    ValidationError {
97        status: u16,
98        message: Option<String>,
99        details: Option<serde_json::Value>,
100        request_id: Option<String>,
101        meta: Option<ResponseMeta>,
102    },
103
104    #[error("resource not found (status {status})")]
105    NotFound {
106        status: u16,
107        message: Option<String>,
108        request_id: Option<String>,
109        meta: Option<ResponseMeta>,
110    },
111
112    #[error("server error (status {status})")]
113    ServerError {
114        status: u16,
115        message: Option<String>,
116        request_id: Option<String>,
117        meta: Option<ResponseMeta>,
118    },
119
120    #[error("api error (status {status})")]
121    ApiError {
122        status: u16,
123        code: Option<String>,
124        message: Option<String>,
125        details: Option<serde_json::Value>,
126        request_id: Option<String>,
127        meta: Option<ResponseMeta>,
128    },
129
130    #[error("invalid header `{name}`")]
131    InvalidHeader { name: String },
132
133    #[error(transparent)]
134    Transport(#[from] reqwest::Error),
135
136    #[error(transparent)]
137    Json(#[from] serde_json::Error),
138
139    #[error(transparent)]
140    Url(#[from] url::ParseError),
141}
142
143impl Error {
144    pub fn status(&self) -> Option<u16> {
145        use Error::*;
146        match self {
147            AuthenticationError { status, .. }
148            | RateLimitError { status, .. }
149            | InsufficientCredits { status, .. }
150            | VisitorMonthlyQuotaExhausted { status, .. }
151            | ValidationError { status, .. }
152            | NotFound { status, .. }
153            | ServerError { status, .. }
154            | ApiError { status, .. } => Some(*status),
155            _ => None,
156        }
157    }
158
159    pub fn request_id(&self) -> Option<&str> {
160        use Error::*;
161        match self {
162            AuthenticationError { request_id, .. }
163            | RateLimitError { request_id, .. }
164            | InsufficientCredits { request_id, .. }
165            | VisitorMonthlyQuotaExhausted { request_id, .. }
166            | ValidationError { request_id, .. }
167            | NotFound { request_id, .. }
168            | ServerError { request_id, .. }
169            | ApiError { request_id, .. } => request_id.as_deref(),
170            _ => None,
171        }
172    }
173
174    pub fn meta(&self) -> Option<&ResponseMeta> {
175        use Error::*;
176        match self {
177            AuthenticationError { meta, .. }
178            | RateLimitError { meta, .. }
179            | InsufficientCredits { meta, .. }
180            | VisitorMonthlyQuotaExhausted { meta, .. }
181            | ValidationError { meta, .. }
182            | NotFound { meta, .. }
183            | ServerError { meta, .. }
184            | ApiError { meta, .. } => meta.as_ref(),
185            _ => None,
186        }
187    }
188}
189
190#[derive(Debug, serde::Deserialize)]
191pub struct ApiErrorBody {
192    pub code: Option<String>,
193    pub error: Option<String>,
194    pub message: Option<String>,
195    pub details: Option<serde_json::Value>,
196    pub quota: Option<serde_json::Value>,
197    pub docs: Option<serde_json::Value>,
198}