api error handling
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Andrey Tkachenko 2023-05-12 11:32:56 +04:00
parent 9fb59879b2
commit 6c947abb18
5 changed files with 36 additions and 12 deletions

1
Cargo.lock generated
View File

@ -607,6 +607,7 @@ dependencies = [
"diesel", "diesel",
"diesel-async", "diesel-async",
"serde", "serde",
"serde_json",
"tokio", "tokio",
] ]

View File

@ -12,4 +12,5 @@ ctxerr = "0.2.5"
diesel = { version = "2.0.4", features = ["chrono"] } diesel = { version = "2.0.4", features = ["chrono"] }
diesel-async = { version = "0.2.2", features = ["postgres", "tokio-postgres", "deadpool"] } diesel-async = { version = "0.2.2", features = ["postgres", "tokio-postgres", "deadpool"] }
serde = { version = "1.0.163", features = ["derive"] } 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"] } tokio = { version = "1.28.0", features = ["parking_lot", "macros", "rt", "rt-multi-thread"] }

29
src/api/error.rs Normal file
View File

@ -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()
}
}

View File

@ -1,3 +1,4 @@
mod error;
mod user; mod user;
use axum::{ use axum::{

View File

@ -6,7 +6,7 @@ use crate::db::{
repos, repos,
}; };
use super::ApiState; use super::{error::Error, ApiState};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct ApiUser { pub struct ApiUser {
@ -18,7 +18,7 @@ pub struct ApiUser {
pub async fn create_user( pub async fn create_user(
State(s): State<ApiState>, State(s): State<ApiState>,
Json(payload): Json<ApiUser>, Json(payload): Json<ApiUser>,
) -> Result<Json<User>, (StatusCode, String)> { ) -> Result<(StatusCode, Json<User>), Error> {
let user = repos::user::create_user( let user = repos::user::create_user(
&s.pool, &s.pool,
NewUser { NewUser {
@ -27,10 +27,9 @@ pub async fn create_user(
email: &payload.email, email: &payload.email,
}, },
) )
.await .await?;
.map_err(internal_error)?;
Ok(Json(user)) Ok((StatusCode::CREATED, Json(user)))
} }
pub async fn list_user(State(s): State<ApiState>) -> (StatusCode, Json<Vec<User>>) { pub async fn list_user(State(s): State<ApiState>) -> (StatusCode, Json<Vec<User>>) {
@ -38,10 +37,3 @@ pub async fn list_user(State(s): State<ApiState>) -> (StatusCode, Json<Vec<User>
(StatusCode::CREATED, Json(user)) (StatusCode::CREATED, Json(user))
} }
fn internal_error<E>(err: E) -> (StatusCode, String)
where
E: std::error::Error,
{
(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
}