diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md index 5cc9649adb..ee930f5315 100644 --- a/axum/CHANGELOG.md +++ b/axum/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # Unreleased +- **added:** Implement `OptionalFromRequest` for `Json` ([#3142]) + +[#3142]: https://github.com/tokio-rs/axum/pull/3142 + # 0.8.0 ## since rc.1 diff --git a/axum/src/json.rs b/axum/src/json.rs index 7082ac8bc3..9cd97730ae 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -1,5 +1,6 @@ use crate::extract::Request; use crate::extract::{rejection::*, FromRequest}; +use axum_core::extract::OptionalFromRequest; use axum_core::response::{IntoResponse, Response}; use bytes::{BufMut, Bytes, BytesMut}; use http::{ @@ -112,6 +113,28 @@ where } } +impl OptionalFromRequest for Json +where + T: DeserializeOwned, + S: Send + Sync, +{ + type Rejection = JsonRejection; + + async fn from_request(req: Request, state: &S) -> Result, Self::Rejection> { + let headers = req.headers(); + if headers.get(header::CONTENT_TYPE).is_some() { + if json_content_type(headers) { + let bytes = Bytes::from_request(req, state).await?; + Ok(Some(Self::from_bytes(&bytes)?)) + } else { + Err(MissingJsonContentType.into()) + } + } else { + Ok(None) + } + } +} + fn json_content_type(headers: &HeaderMap) -> bool { let content_type = if let Some(content_type) = headers.get(header::CONTENT_TYPE) { content_type