mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +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", | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Sampras Lopes
					Sampras Lopes