tdm_server_rust/common/
json_extractor.rs1use async_trait::async_trait;
7use axum::{
8 body::Bytes,
9 extract::{FromRequest, Request},
10 http::{header, StatusCode},
11 response::{IntoResponse, Response},
12};
13use serde::de::DeserializeOwned;
14
15use crate::utils::fast_json;
16
17pub struct AppJson<T>(pub T);
40
41#[async_trait]
42impl<T, S> FromRequest<S> for AppJson<T>
43where
44 T: DeserializeOwned,
45 S: Send + Sync,
46{
47 type Rejection = Response;
49
50 async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
52 let bytes = Bytes::from_request(req, state)
53 .await
54 .map_err(|err| err.into_response())?;
55 if bytes.is_empty() {
56 return Err(json_error(StatusCode::BAD_REQUEST, "Request body is empty"));
57 }
58 fast_json::from_slice(&bytes)
59 .map(AppJson)
60 .map_err(|e| json_error(StatusCode::BAD_REQUEST, &e.to_string()))
61 }
62}
63
64fn json_error(status: StatusCode, msg: &str) -> Response {
66 (
67 status,
68 [(header::CONTENT_TYPE, "application/json;charset=UTF-8")],
69 format!(r#"{{"code":500,"msg":"{msg}","data":null}}"#),
70 )
71 .into_response()
72}