use reqwest::StatusCode;
use crate::http::constants::ERROR_BODY_PREVIEW_LIMIT;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("invalid url: {0}")]
Url(#[from] url::ParseError),
#[error("base url cannot be a base: {0}")]
UrlNotBase(url::Url),
#[error("failed to encode query: {0}")]
Query(#[from] serde_urlencoded::ser::Error),
#[error("failed to serialize request body: {0}")]
Serialize(#[source] serde_json::Error),
#[error("failed to deserialize response ({status}): {source}")]
Deserialize {
status: StatusCode,
body: String,
#[source]
source: serde_json::Error,
},
#[error("http {status}: {body}")]
Status {
status: StatusCode,
body: String,
},
#[error("transport error: {0}")]
Transport(#[from] reqwest::Error),
}
impl Error {
pub fn status(&self) -> Option<StatusCode> {
match self {
Self::Status { status, .. } | Self::Deserialize { status, .. } => Some(*status),
Self::Transport(e) => e.status(),
_ => None,
}
}
pub fn is_timeout(&self) -> bool {
matches!(self, Self::Transport(e) if e.is_timeout())
}
}
pub(crate) fn body_preview(bytes: &[u8]) -> String {
let end = bytes.len().min(ERROR_BODY_PREVIEW_LIMIT);
String::from_utf8_lossy(&bytes[..end]).into_owned()
}