releasy_client/
error.rs

1use std::fmt;
2
3use crate::models::{EnterpriseErrorBody, ErrorBody};
4
5pub type Result<T> = std::result::Result<T, Error>;
6
7#[derive(Debug)]
8pub enum Error {
9    Api {
10        status: u16,
11        error: Option<ErrorBody>,
12        body: Option<String>,
13    },
14    Transport(ureq::Error),
15    InvalidBaseUrl(String),
16    MissingLocationHeader,
17}
18
19impl Error {
20    /// Return the HTTP status code for API errors.
21    pub fn status(&self) -> Option<u16> {
22        match self {
23            Error::Api { status, .. } => Some(*status),
24            _ => None,
25        }
26    }
27
28    /// Return the parsed `ErrorBody` for API errors, when available.
29    pub fn api_error(&self) -> Option<&ErrorBody> {
30        match self {
31            Error::Api { error, .. } => error.as_ref(),
32            _ => None,
33        }
34    }
35
36    /// Parse an `EnterpriseErrorBody` from the raw error body, if present.
37    pub fn enterprise_error(&self) -> Option<EnterpriseErrorBody> {
38        match self {
39            Error::Api { body, .. } => body
40                .as_ref()
41                .and_then(|body| serde_json::from_str::<EnterpriseErrorBody>(body).ok()),
42            _ => None,
43        }
44    }
45
46    /// Return the raw response body for API errors, when available.
47    pub fn body(&self) -> Option<&str> {
48        match self {
49            Error::Api { body, .. } => body.as_deref(),
50            _ => None,
51        }
52    }
53}
54
55impl fmt::Display for Error {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        match self {
58            Error::Api {
59                status,
60                error: Some(error),
61                ..
62            } => write!(
63                f,
64                "api error (status {}): {} ({})",
65                status, error.error.code, error.error.message
66            ),
67            Error::Api { status, .. } => write!(f, "api error (status {})", status),
68            Error::Transport(err) => write!(f, "transport error: {}", err),
69            Error::InvalidBaseUrl(url) => write!(f, "invalid base url: {}", url),
70            Error::MissingLocationHeader => {
71                write!(f, "missing Location header in redirect response")
72            }
73        }
74    }
75}
76
77impl std::error::Error for Error {}
78
79impl From<ureq::Error> for Error {
80    fn from(err: ureq::Error) -> Self {
81        Error::Transport(err)
82    }
83}