Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(response): split http result into smaller manageable files #23

Merged
merged 1 commit into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"

Expand Down
1 change: 1 addition & 0 deletions src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod extractors;
pub mod kernel;
pub mod middlewares;
pub mod server;
pub mod response;
56 changes: 56 additions & 0 deletions src/http/response/defs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use ntex::web::HttpResponse;
use crate::prelude::{AppMessage, AppResult, HttpResult};

pub enum Return<T> {
Success(T, &'static str),
Failure(T, &'static str),
Message(AppMessage),
}

impl<T> Return<T> {
pub fn msg(msg: AppMessage) -> Return<T> {
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<T>: Sized {
fn respond_map<Func>(self, func: Func) -> HttpResult
where
Func: FnOnce(T) -> Return<T>;

fn respond_map_any<Func>(self, map: Func) -> HttpResult
where
Func: FnOnce(Self) -> Return<T>;
}

pub trait StructResponse: Sized {
fn send_response(self) -> HttpResponse;

fn send_struct_result(self) -> Result<HttpResponse, AppMessage>;
}

pub trait OptionResultResponse<T> {
fn is_empty(&self) -> bool;

fn is_error_or_empty(&self) -> bool;

fn get_error_result(self) -> AppResult<T>;

fn send_error(self) -> HttpResult;

fn send_entity(self) -> HttpResult;

fn send_response(self) -> HttpResult;
}
42 changes: 42 additions & 0 deletions src/http/response/mappable.rs
Original file line number Diff line number Diff line change
@@ -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<T: Serialize> MappableResponse<T> for Result<T, BlockingError<AppMessage>> {
fn respond_map<Func>(self, func: Func) -> HttpResult
where
Func: FnOnce(T) -> Return<T>,
{
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<Func>(self, map: Func) -> HttpResult
where
Func: FnOnce(Self) -> Return<T>,
{
format_return(map(self))
}
}

fn format_return<T: Serialize>(ret: Return<T>) -> 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()),
)),
}
}
5 changes: 5 additions & 0 deletions src/http/response/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod defs;
pub mod mappable;
pub mod respond;
pub mod result;
pub mod r#struct;
43 changes: 43 additions & 0 deletions src/http/response/respond.rs
Original file line number Diff line number Diff line change
@@ -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<T> NtexBlockingResultResponder for AppResult<T>
where
T: Sized + Serialize,
{
fn respond(self) -> HttpResult {
self.send_result()
}

fn respond_msg(self, suc: &str) -> HttpResult {
self.send_result_msg(suc)
}
}

impl<T> NtexBlockingResultResponder for Result<T, BlockingError<AppMessage>>
where
T: Serialize + Sized,
{
fn respond(self) -> HttpResult {
<Result<T, AppMessage> as ResultResponse>::send_result(self.into_app_result())
}

fn respond_msg(self, msg: &str) -> HttpResult {
<Result<T, AppMessage> as ResultResponse>::send_result_msg(self.into_app_result(), msg)
}
}

impl NtexBlockingResultResponder for Result<AppMessage, BlockingError<AppMessage>> {
fn respond(self) -> HttpResult {
<Result<AppMessage, AppMessage> as ResultResponse>::send_result(self.into_app_result())
}

fn respond_msg(self, msg: &str) -> HttpResult {
<Result<AppMessage, AppMessage> as ResultResponse>::send_result_msg(
self.into_app_result(),
msg,
)
}
}
75 changes: 75 additions & 0 deletions src/http/response/result.rs
Original file line number Diff line number Diff line change
@@ -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<AppMessage, AppMessage> {
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<T: Serialize> OptionResultResponse<T> for AppResult<T> {
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<T> {
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<T: Serialize> ResultResponse for AppResult<T> {
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),
}
}
}
15 changes: 15 additions & 0 deletions src/http/response/struct.rs
Original file line number Diff line number Diff line change
@@ -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<T: Serialize> StructResponse for T {
fn send_response(self) -> HttpResponse {
json_success(self, None)
}

fn send_struct_result(self) -> HttpResult {
Ok(self.send_response())
}
}
Loading
Loading