From ef0b99b6a01e083101fe2e78e6a9c17e3708bc3c Mon Sep 17 00:00:00 2001 From: Mehul Arora <65443164+infiniteregrets@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:20:40 -0500 Subject: [PATCH] Implement `OptionalFromRequest` for the Json extractor (#3142) --- axum/CHANGELOG.md | 4 ++++ axum/src/json.rs | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md index 5cc9649a..ee930f53 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 7082ac8b..9cd97730 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