pub use std::error::Error as _;
use actix_http::StatusCode;
use actix_web::{HttpResponse, ResponseError};
use super::R;
pub const UNAUTH_ACCESS: u16 = 401;
pub const INVALID_PARAMS: u16 = 413;
pub const INVALID_REQUEST: u16 = 400;
pub const NOT_FOUND_CODE: u16 = 404;
pub const INTERNAL_SERVER_ERROR: u16 = 500;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error2 {
#[error("GenericError: error={}", .0)]
GenericError(String),
#[error("InvalidRequestError: error={}", .0)]
InvalidRequest(String),
#[error("InvalidParam: error={}", .0)]
InvalidParam(String),
}
#[derive(thiserror::Error)]
pub enum Error {
#[error("InvalidCredentials: error={}", .0)]
InvalidCredentials(String),
#[error("InvalidParam: error={}", .0)]
ObjectIdError(#[from] bson::error::Error),
#[error("ReqwestError: error={}", .0)]
ReqwestError(#[from] reqwest::Error),
#[error("IOError: error={}", .0)]
IOError(#[from] std::io::Error),
#[error("SerdeError: error={}", .0)]
SerdeError(#[from] serde_json::Error),
#[error("SQLError: error={}", .0)]
SQLError(#[from] sqlx_core::Error),
#[error(transparent)]
UnexpectedError(#[from] anyhow::Error),
}
impl Error {
pub fn real_error(&self) -> u16 {
match self {
Error::InvalidCredentials(e) => {
log::error!("InvalidCredentials: code={}, error={:?}", UNAUTH_ACCESS, e);
UNAUTH_ACCESS
}
Error::ObjectIdError(e) => {
log::error!(
"ObjectIdError: code={}, error={:?}",
INTERNAL_SERVER_ERROR,
e
);
INTERNAL_SERVER_ERROR
}
Error::ReqwestError(e) => {
log::error!(
"ReqwestError: code={}, error={:?}",
INTERNAL_SERVER_ERROR,
e
);
INTERNAL_SERVER_ERROR
}
Error::IOError(e) => {
log::error!("IOError: code={}, error={:?}", INTERNAL_SERVER_ERROR, e);
INTERNAL_SERVER_ERROR
}
Error::SQLError(e) => {
log::error!("SQLError: code={}, error={:?}", INTERNAL_SERVER_ERROR, e);
INTERNAL_SERVER_ERROR
}
Error::SerdeError(e) => {
log::error!("SerdeError: code={}, error={:?}", INTERNAL_SERVER_ERROR, e);
INTERNAL_SERVER_ERROR
}
Error::UnexpectedError(e) => {
if let Some(error2) = e.downcast_ref::<Error2>() {
return match error2 {
Error2::GenericError(_) => INTERNAL_SERVER_ERROR,
Error2::InvalidRequest(_) => INVALID_REQUEST,
Error2::InvalidParam(_) => INVALID_PARAMS,
};
}
log::error!(
"UnexpectedError: code={}, error={:?}",
INTERNAL_SERVER_ERROR,
e
);
INTERNAL_SERVER_ERROR
}
}
}
pub fn run_time<T>(e: T) -> Self
where
T: std::fmt::Debug,
{
Self::UnexpectedError(anyhow::anyhow!(format!("run_time: error={:?}", e)))
}
pub fn throw<T>(msg: impl Into<String>, e: Option<T>) -> Self
where
T: std::fmt::Debug,
{
Self::UnexpectedError(anyhow::anyhow!(format!(
"throw-{}: error={:?}",
msg.into(),
e
)))
}
pub fn invalid_request(msg: impl Into<String>) -> Self {
Self::UnexpectedError(anyhow::anyhow!(Error2::InvalidRequest(msg.into())))
}
}
impl std::fmt::Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let e = self;
writeln!(f, "{}\n", e)?;
let mut current = e.source();
while let Some(cause) = current {
writeln!(f, "Caused by:\n\t{}", cause)?;
current = cause.source();
}
Ok(())
}
}
impl ResponseError for Error {
fn error_response(&self) -> HttpResponse {
HttpResponse::build(StatusCode::OK)
.content_type("application/json")
.body(serde_json::to_string(&R::failed(self.real_error(), self.to_string())).unwrap())
}
}