1pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
5
6#[derive(Debug, thiserror::Error)]
8pub enum Error {
9 #[error("Client error: {0}")]
11 Client(#[from] ClientError),
12 #[error("Middleware error: {0}")]
14 Middleware(BoxError),
15}
16
17#[derive(Debug, thiserror::Error)]
19#[error("{inner}")]
20pub struct ClientError {
21 #[source]
22 inner: BoxError,
23 kind: ClientErrorKind,
24}
25
26impl ClientError {
27 #[must_use]
29 pub fn is_timeout(&self) -> bool {
30 matches!(self.kind, ClientErrorKind::Timeout)
31 }
32
33 #[must_use]
35 pub fn is_connection(&self) -> bool {
36 matches!(self.kind, ClientErrorKind::Timeout)
37 }
38
39 #[must_use]
41 pub fn is_body(&self) -> bool {
42 matches!(self.kind, ClientErrorKind::Body)
43 }
44}
45
46#[derive(Debug, Clone, Copy)]
47enum ClientErrorKind {
48 Timeout,
49 Connection,
50 Body,
51 Other,
52}
53
54impl From<reqwest::Error> for ClientError {
55 fn from(value: reqwest::Error) -> Self {
56 let kind = if value.is_timeout() {
57 ClientErrorKind::Timeout
58 } else if value.is_connect() {
59 ClientErrorKind::Connection
60 } else if value.is_body() {
61 ClientErrorKind::Body
62 } else {
63 ClientErrorKind::Other
64 };
65
66 Self {
67 inner: Box::new(value),
68 kind,
69 }
70 }
71}
72
73impl From<reqwest::Error> for Error {
74 fn from(value: reqwest::Error) -> Self {
75 Self::Client(value.into())
76 }
77}