Line data Source code
1 : use std::ops::{Deref, DerefMut};
2 :
3 : use axum::extract::{rejection::JsonRejection, FromRequest, Request};
4 : use compute_api::responses::GenericAPIError;
5 : use http::StatusCode;
6 :
7 : /// Custom `Json` extractor, so that we can format errors into
8 : /// `JsonResponse<GenericAPIError>`.
9 : #[derive(Debug, Clone, Copy, Default)]
10 : pub(crate) struct Json<T>(pub T);
11 :
12 : impl<S, T> FromRequest<S> for Json<T>
13 : where
14 : axum::Json<T>: FromRequest<S, Rejection = JsonRejection>,
15 : S: Send + Sync,
16 : {
17 : type Rejection = (StatusCode, axum::Json<GenericAPIError>);
18 :
19 0 : async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
20 0 : match axum::Json::<T>::from_request(req, state).await {
21 0 : Ok(value) => Ok(Self(value.0)),
22 0 : Err(rejection) => Err((
23 0 : rejection.status(),
24 0 : axum::Json(GenericAPIError {
25 0 : error: rejection.body_text().to_lowercase(),
26 0 : }),
27 0 : )),
28 : }
29 0 : }
30 : }
31 :
32 : impl<T> Deref for Json<T> {
33 : type Target = T;
34 :
35 0 : fn deref(&self) -> &Self::Target {
36 0 : &self.0
37 0 : }
38 : }
39 :
40 : impl<T> DerefMut for Json<T> {
41 0 : fn deref_mut(&mut self) -> &mut Self::Target {
42 0 : &mut self.0
43 0 : }
44 : }
|