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