use http_api_client_endpoint::{
http::{Error as HttpError, StatusCode},
Body, Response,
};
use serde::de::DeserializeOwned;
use serde_json::Error as SerdeJsonError;
use url::ParseError as UrlParseError;
use crate::objects::v2::ResponseErrorBody;
#[derive(Debug, Clone)]
pub enum EndpointRet<T>
where
T: core::fmt::Debug + Clone,
{
Ok(T),
Other((StatusCode, Result<ResponseErrorBody, Result<String, Body>>)),
}
#[derive(Debug)]
pub enum EndpointError {
MakeRequestUrlFailed(UrlParseError),
SerRequestBodyFailed(SerdeJsonError),
MakeRequestFailed(HttpError),
DeResponseBodyFailed(SerdeJsonError),
#[cfg(feature = "with_tokio_fs")]
GetFileInfoFailed(std::io::Error),
}
impl core::fmt::Display for EndpointError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{self:?}")
}
}
impl std::error::Error for EndpointError {}
pub fn endpoint_parse_response<T>(response: Response<Body>) -> Result<EndpointRet<T>, EndpointError>
where
T: core::fmt::Debug + Clone + DeserializeOwned,
{
let status = response.status();
match status {
StatusCode::OK => {
let ok_json = serde_json::from_slice::<T>(response.body())
.map_err(EndpointError::DeResponseBodyFailed)?;
Ok(EndpointRet::Ok(ok_json))
}
status => match serde_json::from_slice::<ResponseErrorBody>(response.body()) {
Ok(err_json) => Ok(EndpointRet::Other((status, Ok(err_json)))),
Err(_) => Ok(EndpointRet::Other((
status,
Err(String::from_utf8(response.body().to_owned())
.map_err(|_| response.body().to_owned())),
))),
},
}
}