use reqwest::Url;
use serde_json::Value;
use thiserror::Error;
use crate::{MiddlewareError, MimeType};
#[derive(Debug, Error)]
pub enum RouteError {
#[error("Service discovery error: {0}")]
ServiceDiscovery(anyhow::Error),
#[error("IO error: {0}")]
IoError(std::io::Error),
#[error("Update scheme error: {0} => {1}")]
UpdateScheme(Url, String),
#[error("Update host error: {0} => {1}")]
UpdateHost(Url, String, url::ParseError),
#[error("Update port error: {0} => :{1}")]
UpdatePort(Url, u16),
#[error("Custom error: {0}")]
Custom(String),
}
#[derive(Debug, Error)]
pub enum ApiError {
#[error("Route error: {0}")]
Route(#[from] RouteError),
#[error("Invalid URL: {0}")]
InvalidUrl(reqwest::Error),
#[error("Build request error: {0}")]
BuildRequest(reqwest::Error),
#[error("Generic reqwest error: {0}")]
Reqwest(reqwest::Error),
#[error("Middleware error: {0}")]
Middleware(anyhow::Error),
#[error("Invalid multipart form")]
MultipartForm,
#[error("HTTP Client status error: [{0}] {1}")]
HttpClientStatus(u16, String),
#[error("HTTP Server status error: [{0}] {1}")]
HttpServerStatus(u16, String),
#[error("Unsupported Content-Type: {0}")]
UnsupportedContentType(MimeType),
#[error("Incompatible Content-Type: perfer {0}, actual {1}")]
IncompatibleContentType(MimeType, MimeType),
#[error("Decode response error: {0} => {1}")]
DecodeResponse(MimeType, String),
#[error("Decode json error: {0}")]
DecodeJson(#[from] serde_json::Error),
#[error("Decode xml error: {0}")]
DecodeXml(#[from] quick_xml::DeError),
#[error("Decode text error")]
DecodeText,
#[error("Illegal json: {0}")]
IllegalJson(Value),
#[error("Service error: {0} - {1:?}")]
ServiceError(i32, Option<String>),
#[error("Other error: {0}")]
Other(String),
}
impl ApiError {
pub fn new(code: i32, message: impl ToString) -> Self {
Self::ServiceError(code, Some(message.to_string()))
}
}
impl From<reqwest::Error> for ApiError {
fn from(e: reqwest::Error) -> Self {
if e.is_status() {
let status = e.status().unwrap_or_default();
if status.is_client_error() {
ApiError::HttpClientStatus(status.as_u16(), status.to_string())
} else {
ApiError::HttpServerStatus(status.as_u16(), status.to_string())
}
} else {
ApiError::Reqwest(e)
}
}
}
impl From<MiddlewareError> for ApiError {
fn from(e: MiddlewareError) -> Self {
match e {
MiddlewareError::Reqwest(e) => Self::Reqwest(e),
MiddlewareError::Middleware(e) => Self::Middleware(e),
}
}
}
pub type ApiResult<T> = Result<T, ApiError>;