diff --git a/Cargo.lock b/Cargo.lock index bdff746..ce6fddc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1863,7 +1863,7 @@ dependencies = [ [[package]] name = "medullah-web" -version = "0.3.18" +version = "0.4.0" dependencies = [ "base64 0.22.1", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 408912b..834dfbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "medullah-web" -version = "0.3.18" +version = "0.4.0" edition = "2021" repository = "https://github.com/spiralover/medullah-web" diff --git a/src/http/mod.rs b/src/http/mod.rs index 3b8c031..b57f2cc 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -2,3 +2,4 @@ pub mod extractors; pub mod kernel; pub mod middlewares; pub mod server; +pub mod response; diff --git a/src/http/response/defs.rs b/src/http/response/defs.rs new file mode 100644 index 0000000..7751cab --- /dev/null +++ b/src/http/response/defs.rs @@ -0,0 +1,56 @@ +use ntex::web::HttpResponse; +use crate::prelude::{AppMessage, AppResult, HttpResult}; + +pub enum Return { + Success(T, &'static str), + Failure(T, &'static str), + Message(AppMessage), +} + +impl Return { + pub fn msg(msg: AppMessage) -> Return { + Return::Message(msg) + } +} + +pub trait ResultResponse { + fn send_result(self) -> HttpResult; + + fn send_result_msg(self, msg: &str) -> HttpResult; +} + +pub trait NtexBlockingResultResponder { + fn respond(self) -> HttpResult; + + fn respond_msg(self, suc: &str) -> HttpResult; +} + +pub trait MappableResponse: Sized { + fn respond_map(self, func: Func) -> HttpResult + where + Func: FnOnce(T) -> Return; + + fn respond_map_any(self, map: Func) -> HttpResult + where + Func: FnOnce(Self) -> Return; +} + +pub trait StructResponse: Sized { + fn send_response(self) -> HttpResponse; + + fn send_struct_result(self) -> Result; +} + +pub trait OptionResultResponse { + fn is_empty(&self) -> bool; + + fn is_error_or_empty(&self) -> bool; + + fn get_error_result(self) -> AppResult; + + fn send_error(self) -> HttpResult; + + fn send_entity(self) -> HttpResult; + + fn send_response(self) -> HttpResult; +} diff --git a/src/http/response/mappable.rs b/src/http/response/mappable.rs new file mode 100644 index 0000000..18d812f --- /dev/null +++ b/src/http/response/mappable.rs @@ -0,0 +1,42 @@ +use ntex::http::error::BlockingError; +use ntex::http::StatusCode; +use serde::Serialize; + +use crate::helpers::responder::{json_error, json_success}; +use crate::http::response::defs::{MappableResponse, Return}; +use crate::prelude::AppMessage; +use crate::results::HttpResult; + +impl MappableResponse for Result> { + fn respond_map(self, func: Func) -> HttpResult + where + Func: FnOnce(T) -> Return, + { + match self { + Ok(data) => format_return(func(data)), + Err(err) => { + let msg = AppMessage::BlockingNtexErrorOuterBoxed(Box::new(err)); + msg.into_http_result() + } + } + } + + fn respond_map_any(self, map: Func) -> HttpResult + where + Func: FnOnce(Self) -> Return, + { + format_return(map(self)) + } +} + +fn format_return(ret: Return) -> HttpResult { + match ret { + Return::Success(item, msg) => Ok(json_success(item, Some(msg.to_string()))), + Return::Message(msg) => msg.into_http_result(), + Return::Failure(item, msg) => Ok(json_error( + item, + StatusCode::BAD_REQUEST, + Some(msg.to_string()), + )), + } +} diff --git a/src/http/response/mod.rs b/src/http/response/mod.rs new file mode 100644 index 0000000..0987016 --- /dev/null +++ b/src/http/response/mod.rs @@ -0,0 +1,5 @@ +pub mod defs; +pub mod mappable; +pub mod respond; +pub mod result; +pub mod r#struct; diff --git a/src/http/response/respond.rs b/src/http/response/respond.rs new file mode 100644 index 0000000..61d1494 --- /dev/null +++ b/src/http/response/respond.rs @@ -0,0 +1,43 @@ +use ntex::http::error::BlockingError; +use serde::Serialize; +use crate::http::response::defs::{ResultResponse, NtexBlockingResultResponder}; +use crate::prelude::{AppMessage, AppResult, HttpResult, IntoAppResult}; + +impl NtexBlockingResultResponder for AppResult +where + T: Sized + Serialize, +{ + fn respond(self) -> HttpResult { + self.send_result() + } + + fn respond_msg(self, suc: &str) -> HttpResult { + self.send_result_msg(suc) + } +} + +impl NtexBlockingResultResponder for Result> +where + T: Serialize + Sized, +{ + fn respond(self) -> HttpResult { + as ResultResponse>::send_result(self.into_app_result()) + } + + fn respond_msg(self, msg: &str) -> HttpResult { + as ResultResponse>::send_result_msg(self.into_app_result(), msg) + } +} + +impl NtexBlockingResultResponder for Result> { + fn respond(self) -> HttpResult { + as ResultResponse>::send_result(self.into_app_result()) + } + + fn respond_msg(self, msg: &str) -> HttpResult { + as ResultResponse>::send_result_msg( + self.into_app_result(), + msg, + ) + } +} diff --git a/src/http/response/result.rs b/src/http/response/result.rs new file mode 100644 index 0000000..bc6ef9f --- /dev/null +++ b/src/http/response/result.rs @@ -0,0 +1,75 @@ +use serde::Serialize; +use crate::helpers::responder::json_success; +use crate::http::response::defs::{OptionResultResponse, ResultResponse}; +use crate::prelude::{AppMessage, AppResult, HttpResult}; + +impl ResultResponse for Result { + fn send_result(self) -> HttpResult { + match self { + Ok(data) => Ok(data.into_response()), + Err(err) => Err(err), + } + } + + fn send_result_msg(self, _msg: &str) -> HttpResult { + self.send_result() + } +} + +impl OptionResultResponse for AppResult { + fn is_empty(&self) -> bool { + if let Err(AppMessage::EntityNotFound(..)) = self { + return true; + } + + false + } + + fn is_error_or_empty(&self) -> bool { + self.as_ref().is_err() || self.is_empty() + } + + fn get_error_result(self) -> AppResult { + if self.is_err() { + return Err(self.err().unwrap()); + } + + // let entity = self. + panic!("Cannot acquire error on successful database action") + } + + fn send_error(self) -> HttpResult { + if self.is_err() { + return Err(self.err().unwrap()); + } + + Err(AppMessage::WarningMessage("Internal Server Error :)")) + } + + fn send_entity(self) -> HttpResult { + Ok(json_success(self.unwrap(), None)) + } + + fn send_response(self) -> HttpResult { + match self.is_error_or_empty() { + true => self.send_error(), + false => self.send_entity(), + } + } +} + +impl ResultResponse for AppResult { + fn send_result(self) -> HttpResult { + match self { + Ok(data) => Ok(json_success(data, None)), + Err(err) => Err(err), + } + } + + fn send_result_msg(self, msg: &str) -> HttpResult { + match self { + Ok(data) => Ok(json_success(data, Some(msg.to_string()))), + Err(err) => Err(err), + } + } +} diff --git a/src/http/response/struct.rs b/src/http/response/struct.rs new file mode 100644 index 0000000..a8fb3a4 --- /dev/null +++ b/src/http/response/struct.rs @@ -0,0 +1,15 @@ +use ntex::web::HttpResponse; +use serde::Serialize; +use crate::helpers::responder::json_success; +use crate::http::response::defs::StructResponse; +use crate::prelude::HttpResult; + +impl StructResponse for T { + fn send_response(self) -> HttpResponse { + json_success(self, None) + } + + fn send_struct_result(self) -> HttpResult { + Ok(self.send_response()) + } +} diff --git a/src/results/http_result.rs b/src/results/http_result.rs deleted file mode 100644 index 1f27730..0000000 --- a/src/results/http_result.rs +++ /dev/null @@ -1,164 +0,0 @@ -use ntex::http::error::BlockingError; -use ntex::web::HttpResponse; -use serde::Serialize; - -use crate::enums::app_message::AppMessage; -use crate::helpers::responder::json_success; -use crate::prelude::IntoAppResult; -use crate::results::{AppResult, HttpResult}; - -pub trait ErroneousResponse { - fn send_result(self) -> HttpResult; - - fn send_result_msg(self, msg: &str) -> HttpResult; -} - -pub trait NtexBlockingResultResponder { - fn respond(self) -> HttpResult; - - fn respond_msg(self, suc: &str) -> HttpResult; -} - -pub trait StructResponse: Sized { - fn send_response(self) -> HttpResponse; - - fn send_struct_result(self) -> Result; -} - -pub trait ErroneousOptionResponse { - fn is_empty(&self) -> bool; - - fn is_error_or_empty(&self) -> bool; - - fn get_error_result(self) -> AppResult; - - fn send_error(self) -> HttpResult; - - fn send_entity(self) -> HttpResult; - - fn send_response(self) -> HttpResult; -} - -impl StructResponse for T { - fn send_response(self) -> HttpResponse { - json_success(self, None) - } - - fn send_struct_result(self) -> HttpResult { - Ok(self.send_response()) - } -} - -impl ErroneousResponse for Result { - fn send_result(self) -> HttpResult { - if self.is_err() { - return Err(self.err().unwrap()); - } - - Ok(self.unwrap().into_response()) - } - - fn send_result_msg(self, _msg: &str) -> HttpResult { - self.send_result() - } -} - -impl ErroneousOptionResponse for AppResult { - fn is_empty(&self) -> bool { - if let Err(AppMessage::EntityNotFound(..)) = self { - return true; - } - - false - } - - fn is_error_or_empty(&self) -> bool { - self.as_ref().is_err() || self.is_empty() - } - - fn get_error_result(self) -> AppResult { - if self.is_err() { - return Err(self.err().unwrap()); - } - - // let entity = self. - panic!("Cannot acquire error on successful database action") - } - - fn send_error(self) -> HttpResult { - if self.is_err() { - return Err(self.err().unwrap()); - } - - Err(AppMessage::WarningMessage("Internal Server Error :)")) - } - - fn send_entity(self) -> HttpResult { - Ok(json_success(self.unwrap(), None)) - } - - fn send_response(self) -> HttpResult { - if self.is_error_or_empty() { - return self.send_error(); - } - - self.send_entity() - } -} - -impl ErroneousResponse for AppResult { - fn send_result(self) -> HttpResult { - if self.is_err() { - return Err(self.err().unwrap()); - } - - Ok(json_success(self.unwrap(), None)) - } - - fn send_result_msg(self, msg: &str) -> HttpResult { - if self.is_err() { - return Err(self.err().unwrap()); - } - - Ok(json_success(self.unwrap(), Some(msg.to_string()))) - } -} - -impl NtexBlockingResultResponder for AppResult -where - T: Sized + Serialize, -{ - fn respond(self) -> HttpResult { - self.send_result() - } - - fn respond_msg(self, suc: &str) -> HttpResult { - self.send_result_msg(suc) - } -} - -impl NtexBlockingResultResponder for Result> -where - T: Serialize + Sized, -{ - fn respond(self) -> HttpResult { - as ErroneousResponse>::send_result(self.into_app_result()) - } - - fn respond_msg(self, msg: &str) -> HttpResult { - as ErroneousResponse>::send_result_msg(self.into_app_result(), msg) - } -} - -impl NtexBlockingResultResponder for Result> { - fn respond(self) -> HttpResult { - as ErroneousResponse>::send_result(self.into_app_result()) - } - - fn respond_msg(self, msg: &str) -> HttpResult { - as ErroneousResponse>::send_result_msg( - self.into_app_result(), - msg, - ) - } -} diff --git a/src/results/mod.rs b/src/results/mod.rs index ef7c8ec..4b3c353 100644 --- a/src/results/mod.rs +++ b/src/results/mod.rs @@ -1,8 +1,6 @@ use crate::enums::app_message::AppMessage; pub mod app_result; -#[cfg(feature = "feat-ntex")] -pub mod http_result; pub mod redis_result; pub type AppResult = Result;