brokapi_alor_protocol/error.rs
1//! Errors of the ALOR protocol layer.
2//!
3//! [`AlorApiError`] is what every client method returns. The connector crate maps it to the broker-independent
4//! error of `brokapi-core`.
5
6use thiserror::Error;
7
8/// A failure of the HTTP or WebSocket protocol layer, in the broker's own terms.
9#[derive(Error, Debug)]
10pub enum AlorApiError {
11 /// The HTTP call failed: no status means no answer (a break, a timeout, a refused connection).
12 #[error("HTTP error: {message}")]
13 Http {
14 /// The HTTP status, if the broker answered.
15 status: Option<u16>,
16 /// The text of the broker's error body, or the text of the transport error.
17 message: String,
18 },
19
20 /// The WebSocket failed or the broker sent an error message on it.
21 #[error("WebSocket error: {message}")]
22 Ws {
23 /// The code of the broker's error message (`httpCode`), if any.
24 code: Option<u16>,
25 /// What happened.
26 message: String,
27 },
28
29 /// The authorization server refused the refresh token (revoked, expired, or of another contour).
30 #[error("authorization error: {message}")]
31 Auth {
32 /// The text the server gave.
33 message: String,
34 },
35
36 /// HTTP 404: the broker does not know this order, instrument or portfolio.
37 #[error("not found: {message}")]
38 NotFound {
39 /// The text of the broker's error body.
40 message: String,
41 },
42
43 /// An answer that is a success but is not the JSON the model expects.
44 #[error("parse error: {0}")]
45 Parse(String),
46
47 /// HTTP 429: the request limit of the broker is exceeded.
48 #[error("rate limit exceeded")]
49 RateLimitExceeded,
50
51 /// A subscription cannot be made (a limit of the session, or the session is closed).
52 #[error("subscription error: {message}")]
53 Subscription {
54 /// What happened.
55 message: String,
56 },
57}
58
59/// The error body of the broker: `{"message": "...", "code": "..."}`, with more fields for some errors.
60#[derive(Debug, serde::Deserialize)]
61pub struct ApiErrorBody {
62 /// The text of the error.
63 #[serde(default)]
64 pub message: Option<String>,
65 /// The code of the error, if the broker gives one.
66 #[serde(default)]
67 pub code: Option<String>,
68}
69
70impl From<reqwest::Error> for AlorApiError {
71 fn from(err: reqwest::Error) -> Self {
72 AlorApiError::Http {
73 status: err.status().map(|s| s.as_u16()),
74 message: err.to_string(),
75 }
76 }
77}
78
79impl From<serde_json::Error> for AlorApiError {
80 fn from(err: serde_json::Error) -> Self {
81 AlorApiError::Parse(err.to_string())
82 }
83}
84
85impl From<url::ParseError> for AlorApiError {
86 fn from(err: url::ParseError) -> Self {
87 AlorApiError::Parse(err.to_string())
88 }
89}