use std::error::Error;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;
use std::io::Read;
use http::StatusCode;
#[derive(Debug)]
#[non_exhaustive]
pub enum HttpClientError {
StatusCode(StatusCode),
InvalidUrl(Box<dyn Error + Send + Sync>),
Other(Box<dyn Error + Send + Sync>),
}
impl Display for HttpClientError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::StatusCode(code) => {
write!(
f,
"HTTP request failed with status code {code} {}",
code.canonical_reason().unwrap_or("")
)
},
Self::Other(err) => write!(f, "HTTP client error: {err}"),
Self::InvalidUrl(error) => {
write!(f, "Invalid URL: {error}")
},
}
}
}
impl Error for HttpClientError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::StatusCode(_) => None,
Self::InvalidUrl(err) | Self::Other(err) => Some(&**err),
}
}
}
pub trait Readable: Read + Debug {}
impl<R> Readable for R where R: Read + Debug {}
pub trait HttpClient: Debug {
fn get(&self, url: &str) -> Result<Box<dyn Readable>, HttpClientError>;
}