tdm_server_rust/common/
json_extractor.rs1use axum::{
7 body::Bytes,
8 extract::{FromRequest, Request},
9 http::{header, StatusCode},
10 response::{IntoResponse, Response},
11};
12use async_trait::async_trait;
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(
57 StatusCode::BAD_REQUEST,
58 "Request body is empty",
59 ));
60 }
61 fast_json::from_slice(&bytes)
62 .map(AppJson)
63 .map_err(|e| json_error(StatusCode::BAD_REQUEST, &e.to_string()))
64 }
65}
66
67fn json_error(status: StatusCode, msg: &str) -> Response {
69 (
70 status,
71 [(header::CONTENT_TYPE, "application/json;charset=UTF-8")],
72 format!(r#"{{"code":500,"msg":"{msg}","data":null}}"#),
73 )
74 .into_response()
75}