Skip to content

Commit

Permalink
chore: add custom json extractor with problem details rejection response
Browse files Browse the repository at this point in the history
  • Loading branch information
pnwatin committed Mar 29, 2024
1 parent 40cc847 commit e8a37da
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/extractors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::error::Error;

use axum::{
async_trait,
extract::{rejection::JsonRejection, FromRequest, Request},
response::IntoResponse,
};
use problemdetails::Problem;
use serde::Serialize;

pub struct Json<T>(pub T);

#[async_trait]
impl<S, T> FromRequest<S> for Json<T>
where
axum::Json<T>: FromRequest<S, Rejection = JsonRejection>,
S: Send + Sync,
{
type Rejection = Problem;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
match axum::Json::<T>::from_request(req, state).await {
Ok(value) => Ok(Self(value.0)),
Err(rejection) => Err(match rejection {
JsonRejection::MissingJsonContentType(err) => problemdetails::new(err.status())
.with_title("Invalid Content-Type header.")
.with_detail("Content-Type header either missing or invalid - please add `Content-Type: application/json` header."),
JsonRejection::JsonSyntaxError(err) => problemdetails::new(err.status())
.with_title("Invalid json syntax.")
.with_detail("Provided json body contains a syntax error - please fix it.")
.with_value("error", err.source().map(|e| e.to_string()).unwrap_or_default()),
JsonRejection::JsonDataError(err) => problemdetails::new(err.status())
.with_title("Invalid json data.")
.with_detail("Provided json body contains invalid or missing data - please fix it.")
.with_value("error", err.source().map(|e| e.to_string()).unwrap_or_default()),
JsonRejection::BytesRejection(err) => problemdetails::new(err.status()),
_ => problemdetails::new(rejection.status()),
}),
}
}
}

impl<T> IntoResponse for Json<T>
where
T: Serialize,
{
fn into_response(self) -> axum::response::Response {
axum::Json(self.0).into_response()
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod domain;
pub mod extractors;
pub mod handlers;
pub mod settings;
pub mod startup;
Expand Down

0 comments on commit e8a37da

Please sign in to comment.