From 6c947abb18fab626b07de541ac978968af21ab4c Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Fri, 12 May 2023 11:32:56 +0400 Subject: [PATCH] api error handling --- Cargo.lock | 1 + Cargo.toml | 1 + src/api/error.rs | 29 +++++++++++++++++++++++++++++ src/api/mod.rs | 1 + src/api/user.rs | 16 ++++------------ 5 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 src/api/error.rs diff --git a/Cargo.lock b/Cargo.lock index 0a41eb3..6ddf7a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,7 @@ dependencies = [ "diesel", "diesel-async", "serde", + "serde_json", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 3c2b0cd..ce967f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ ctxerr = "0.2.5" diesel = { version = "2.0.4", features = ["chrono"] } diesel-async = { version = "0.2.2", features = ["postgres", "tokio-postgres", "deadpool"] } serde = { version = "1.0.163", features = ["derive"] } +serde_json = "1.0.96" tokio = { version = "1.28.0", features = ["parking_lot", "macros", "rt", "rt-multi-thread"] } diff --git a/src/api/error.rs b/src/api/error.rs new file mode 100644 index 0000000..e4fd97c --- /dev/null +++ b/src/api/error.rs @@ -0,0 +1,29 @@ +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, + Json, +}; +use ctxerr::ctxerr; +use serde_json::json; + +#[ctxerr] +pub enum ErrorKind { + #[error("{0}")] + InternalError(#[from] crate::Error), +} + +impl IntoResponse for Error { + fn into_response(self) -> Response { + let (status, error_message) = match self.kind { + ErrorKind::InternalError(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()), + }; + + ( + status, + Json(json! ({ + "error": error_message, + })), + ) + .into_response() + } +} diff --git a/src/api/mod.rs b/src/api/mod.rs index fb1387d..39819b5 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,3 +1,4 @@ +mod error; mod user; use axum::{ diff --git a/src/api/user.rs b/src/api/user.rs index 8870c36..68044c8 100644 --- a/src/api/user.rs +++ b/src/api/user.rs @@ -6,7 +6,7 @@ use crate::db::{ repos, }; -use super::ApiState; +use super::{error::Error, ApiState}; #[derive(Deserialize)] pub struct ApiUser { @@ -18,7 +18,7 @@ pub struct ApiUser { pub async fn create_user( State(s): State, Json(payload): Json, -) -> Result, (StatusCode, String)> { +) -> Result<(StatusCode, Json), Error> { let user = repos::user::create_user( &s.pool, NewUser { @@ -27,10 +27,9 @@ pub async fn create_user( email: &payload.email, }, ) - .await - .map_err(internal_error)?; + .await?; - Ok(Json(user)) + Ok((StatusCode::CREATED, Json(user))) } pub async fn list_user(State(s): State) -> (StatusCode, Json>) { @@ -38,10 +37,3 @@ pub async fn list_user(State(s): State) -> (StatusCode, Json (StatusCode::CREATED, Json(user)) } - -fn internal_error(err: E) -> (StatusCode, String) -where - E: std::error::Error, -{ - (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) -}