use crate::BoxError; use crate::{ extract::{has_content_type, rejection::*, take_body, FromRequest, RequestParts}, response::IntoResponse, }; use async_trait::async_trait; use bytes::Bytes; use http::{ header::{self, HeaderValue}, StatusCode, }; use http_body::Full; use hyper::Response; use serde::{de::DeserializeOwned, Serialize}; use std::{ convert::Infallible, ops::{Deref, DerefMut}, }; /// JSON Extractor/Response /// /// When used as an extractor, it can deserialize request bodies into some type that /// implements [`serde::Serialize`]. If the request body cannot be parsed, or it does not contain /// the `Content-Type: application/json` header, it will reject the request and return a /// `400 Bad Request` response. /// /// # Extractor example /// /// ```rust,no_run /// use axum::{ /// extract, /// handler::post, /// Router, /// }; /// use serde::Deserialize; /// /// #[derive(Deserialize)] /// struct CreateUser { /// email: String, /// password: String, /// } /// /// async fn create_user(extract::Json(payload): extract::Json) { /// // payload is a `CreateUser` /// } /// /// let app = Router::new().route("/users", post(create_user)); /// # async { /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` /// /// When used as a response, it can serialize any type that implements [`serde::Serialize`] to `JSON`, /// and will automatically set `Content-Type: application/json` header. /// /// # Response example /// /// ``` /// use axum::{ /// extract::Path, /// handler::get, /// Router, /// Json, /// }; /// use serde::Serialize; /// use uuid::Uuid; /// /// #[derive(Serialize)] /// struct User { /// id: Uuid, /// username: String, /// } /// /// async fn get_user(Path(user_id) : Path) -> Json { /// let user = find_user(user_id).await; /// Json(user) /// } /// /// async fn find_user(user_id: Uuid) -> User { /// // ... /// # unimplemented!() /// } /// /// let app = Router::new().route("/users/:id", get(get_user)); /// # async { /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` #[derive(Debug, Clone, Copy, Default)] pub struct Json(pub T); #[async_trait] impl FromRequest for Json where T: DeserializeOwned, B: http_body::Body + Send, B::Data: Send, B::Error: Into, { type Rejection = JsonRejection; async fn from_request(req: &mut RequestParts) -> Result { use bytes::Buf; if has_content_type(req, "application/json")? { let body = take_body(req)?; let buf = hyper::body::aggregate(body) .await .map_err(InvalidJsonBody::from_err)?; let value = serde_json::from_reader(buf.reader()).map_err(InvalidJsonBody::from_err)?; Ok(Json(value)) } else { Err(MissingJsonContentType.into()) } } } impl Deref for Json { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for Json { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl From for Json { fn from(inner: T) -> Self { Self(inner) } } impl IntoResponse for Json where T: Serialize, { type Body = Full; type BodyError = Infallible; fn into_response(self) -> Response { let bytes = match serde_json::to_vec(&self.0) { Ok(res) => res, Err(err) => { return Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .header(header::CONTENT_TYPE, "text/plain") .body(Full::from(err.to_string())) .unwrap(); } }; let mut res = Response::new(Full::from(bytes)); res.headers_mut().insert( header::CONTENT_TYPE, HeaderValue::from_static("application/json"), ); res } }