mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
Add a base struct for api error responses (#524)
Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com>
This commit is contained in:
28
crates/api_models/src/errors/actix.rs
Normal file
28
crates/api_models/src/errors/actix.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use super::types::ApiErrorResponse;
|
||||
|
||||
impl actix_web::ResponseError for ApiErrorResponse {
|
||||
fn status_code(&self) -> reqwest::StatusCode {
|
||||
use reqwest::StatusCode;
|
||||
|
||||
match self {
|
||||
Self::Unauthorized(_) => StatusCode::UNAUTHORIZED,
|
||||
Self::ForbiddenCommonResource(_) => StatusCode::FORBIDDEN,
|
||||
Self::ForbiddenPrivateResource(_) => StatusCode::NOT_FOUND,
|
||||
Self::Conflict(_) => StatusCode::CONFLICT,
|
||||
Self::Gone(_) => StatusCode::GONE,
|
||||
Self::Unprocessable(_) => StatusCode::UNPROCESSABLE_ENTITY,
|
||||
Self::InternalServerError(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::NotImplemented(_) => StatusCode::NOT_IMPLEMENTED,
|
||||
Self::ConnectorError(_, code) => *code,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> actix_web::HttpResponse {
|
||||
use actix_web::http::header;
|
||||
|
||||
actix_web::HttpResponseBuilder::new(self.status_code())
|
||||
.insert_header((header::CONTENT_TYPE, mime::APPLICATION_JSON))
|
||||
.insert_header((header::VIA, "Juspay_Router"))
|
||||
.body(self.to_string())
|
||||
}
|
||||
}
|
||||
3
crates/api_models/src/errors/mod.rs
Normal file
3
crates/api_models/src/errors/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod actix;
|
||||
pub mod serde;
|
||||
pub mod types;
|
||||
23
crates/api_models/src/errors/serde.rs
Normal file
23
crates/api_models/src/errors/serde.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use serde::{ser::SerializeMap, Serialize};
|
||||
|
||||
use super::types::ApiErrorResponse;
|
||||
|
||||
impl Serialize for ApiErrorResponse {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut map = serializer.serialize_map(Some(3))?;
|
||||
map.serialize_entry("error_type", self.error_type())?;
|
||||
map.serialize_entry(
|
||||
"error_code",
|
||||
&format!(
|
||||
"{}_{}",
|
||||
self.get_internal_error().sub_code,
|
||||
self.get_internal_error().error_identifier
|
||||
),
|
||||
)?;
|
||||
map.serialize_entry("error_message", self.get_internal_error().error_message)?;
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
68
crates/api_models/src/errors/types.rs
Normal file
68
crates/api_models/src/errors/types.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use reqwest::StatusCode;
|
||||
|
||||
pub enum ErrorType {
|
||||
InvalidRequestError,
|
||||
RouterError,
|
||||
ConnectorError,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
pub struct ApiError {
|
||||
pub sub_code: &'static str,
|
||||
pub error_identifier: u8,
|
||||
pub error_message: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ApiErrorResponse {
|
||||
Unauthorized(ApiError),
|
||||
ForbiddenCommonResource(ApiError),
|
||||
ForbiddenPrivateResource(ApiError),
|
||||
Conflict(ApiError),
|
||||
Gone(ApiError),
|
||||
Unprocessable(ApiError),
|
||||
InternalServerError(ApiError),
|
||||
NotImplemented(ApiError),
|
||||
ConnectorError(ApiError, StatusCode),
|
||||
}
|
||||
|
||||
impl ::core::fmt::Display for ApiErrorResponse {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
r#"{{"error":{}}}"#,
|
||||
serde_json::to_string(self.get_internal_error())
|
||||
.unwrap_or_else(|_| "API error response".to_string())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiErrorResponse {
|
||||
pub(crate) fn get_internal_error(&self) -> &ApiError {
|
||||
match self {
|
||||
Self::Unauthorized(i)
|
||||
| Self::ForbiddenCommonResource(i)
|
||||
| Self::ForbiddenPrivateResource(i)
|
||||
| Self::Conflict(i)
|
||||
| Self::Gone(i)
|
||||
| Self::Unprocessable(i)
|
||||
| Self::InternalServerError(i)
|
||||
| Self::NotImplemented(i)
|
||||
| Self::ConnectorError(i, _) => i,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn error_type(&self) -> &str {
|
||||
match self {
|
||||
Self::Unauthorized(_)
|
||||
| Self::ForbiddenCommonResource(_)
|
||||
| Self::ForbiddenPrivateResource(_)
|
||||
| Self::Conflict(_)
|
||||
| Self::Gone(_)
|
||||
| Self::Unprocessable(_)
|
||||
| Self::NotImplemented(_) => "invalid_request",
|
||||
Self::InternalServerError(_) => "api",
|
||||
Self::ConnectorError(_, _) => "connector",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ pub mod cards;
|
||||
pub mod customers;
|
||||
pub mod disputes;
|
||||
pub mod enums;
|
||||
pub mod errors;
|
||||
pub mod files;
|
||||
pub mod mandates;
|
||||
pub mod payment_methods;
|
||||
|
||||
Reference in New Issue
Block a user