From ceab2437b7500ee64cf5cc9aafb3b2d92bbe7de1 Mon Sep 17 00:00:00 2001 From: wayne warren Date: Thu, 28 Sep 2023 15:48:11 -0600 Subject: [PATCH 1/7] Json: add from_bytes method, use that in 'impl FromRequest' Signed-off-by: wayne warren --- axum/src/json.rs | 67 ++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/axum/src/json.rs b/axum/src/json.rs index 74541c1e11..89e748343d 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -103,31 +103,7 @@ where async fn from_request(req: Request, state: &S) -> Result { if json_content_type(req.headers()) { let bytes = Bytes::from_request(req, state).await?; - let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); - - let value = match serde_path_to_error::deserialize(deserializer) { - Ok(value) => value, - Err(err) => { - let rejection = match err.inner().classify() { - serde_json::error::Category::Data => JsonDataError::from_err(err).into(), - serde_json::error::Category::Syntax | serde_json::error::Category::Eof => { - JsonSyntaxError::from_err(err).into() - } - serde_json::error::Category::Io => { - if cfg!(debug_assertions) { - // we don't use `serde_json::from_reader` and instead always buffer - // bodies first, so we shouldn't encounter any IO errors - unreachable!() - } else { - JsonSyntaxError::from_err(err).into() - } - } - }; - return Err(rejection); - } - }; - - Ok(Json(value)) + Self::from_bytes(&bytes) } else { Err(MissingJsonContentType.into()) } @@ -167,6 +143,47 @@ impl From for Json { } } +impl Json +where + T: DeserializeOwned, +{ + /// Construct a `Json` from `&Bytes`. Most users should prefer to use the `FromRequest` impl + /// but special cases may require first extracting a `Request` into `Bytes` then optionally + /// constructing a `Json`. + /// + /// An example where this would be useful would be one in which a service needs to pass through + /// or otherwise preserve the exact byte representation of the request while also interrogating + /// it for metadata that may be useful in determining exactly what to do with the preserved + /// bytes. + fn from_bytes(bytes: &Bytes) -> Result { + let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); + + let value = match serde_path_to_error::deserialize(deserializer) { + Ok(value) => value, + Err(err) => { + let rejection = match err.inner().classify() { + serde_json::error::Category::Data => JsonDataError::from_err(err).into(), + serde_json::error::Category::Syntax | serde_json::error::Category::Eof => { + JsonSyntaxError::from_err(err).into() + } + serde_json::error::Category::Io => { + if cfg!(debug_assertions) { + // we don't use `serde_json::from_reader` and instead always buffer + // bodies first, so we shouldn't encounter any IO errors + unreachable!() + } else { + JsonSyntaxError::from_err(err).into() + } + } + }; + return Err(rejection); + } + }; + + Ok(Json(value)) + } +} + impl IntoResponse for Json where T: Serialize, From 86cf7e0b2fe1b5f6260c915a6dca3a9ec97c68b0 Mon Sep 17 00:00:00 2001 From: wayne warren Date: Thu, 28 Sep 2023 23:05:43 -0600 Subject: [PATCH 2/7] make Json::from_bytes public --- axum/src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/src/json.rs b/axum/src/json.rs index 89e748343d..f44e509ae5 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -155,7 +155,7 @@ where /// or otherwise preserve the exact byte representation of the request while also interrogating /// it for metadata that may be useful in determining exactly what to do with the preserved /// bytes. - fn from_bytes(bytes: &Bytes) -> Result { + pub fn from_bytes(bytes: &Bytes) -> Result { let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); let value = match serde_path_to_error::deserialize(deserializer) { From 8e491a76cf3ed9950bc5fd6e3dc8aee0c09513a0 Mon Sep 17 00:00:00 2001 From: wayne Date: Fri, 29 Sep 2023 11:03:22 -0600 Subject: [PATCH 3/7] Json::from_bytes: use &[u8] instead of &Bytes Co-authored-by: Jonas Platte --- axum/src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/src/json.rs b/axum/src/json.rs index f44e509ae5..fa8476f38e 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -155,7 +155,7 @@ where /// or otherwise preserve the exact byte representation of the request while also interrogating /// it for metadata that may be useful in determining exactly what to do with the preserved /// bytes. - pub fn from_bytes(bytes: &Bytes) -> Result { + pub fn from_bytes(bytes: &[u8]) -> Result { let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); let value = match serde_path_to_error::deserialize(deserializer) { From edca39fecb115cd94e80763ac1db7c23d5d8c827 Mon Sep 17 00:00:00 2001 From: wayne Date: Fri, 29 Sep 2023 11:03:53 -0600 Subject: [PATCH 4/7] Update axum/src/json.rs Co-authored-by: Jonas Platte --- axum/src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/src/json.rs b/axum/src/json.rs index fa8476f38e..9c050a0bff 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -156,7 +156,7 @@ where /// it for metadata that may be useful in determining exactly what to do with the preserved /// bytes. pub fn from_bytes(bytes: &[u8]) -> Result { - let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); + let deserializer = &mut serde_json::Deserializer::from_slice(bytes); let value = match serde_path_to_error::deserialize(deserializer) { Ok(value) => value, From b20962abddc6ad547f0d4def05edeb685b3e2859 Mon Sep 17 00:00:00 2001 From: wayne warren Date: Fri, 29 Sep 2023 11:09:46 -0600 Subject: [PATCH 5/7] remove potentially confusing docstring paragraph --- axum/src/json.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/axum/src/json.rs b/axum/src/json.rs index 9c050a0bff..69ac22f899 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -150,11 +150,6 @@ where /// Construct a `Json` from `&Bytes`. Most users should prefer to use the `FromRequest` impl /// but special cases may require first extracting a `Request` into `Bytes` then optionally /// constructing a `Json`. - /// - /// An example where this would be useful would be one in which a service needs to pass through - /// or otherwise preserve the exact byte representation of the request while also interrogating - /// it for metadata that may be useful in determining exactly what to do with the preserved - /// bytes. pub fn from_bytes(bytes: &[u8]) -> Result { let deserializer = &mut serde_json::Deserializer::from_slice(bytes); From fc41c7e9253736cc5b7112d3ea6e0033b78a285a Mon Sep 17 00:00:00 2001 From: wayne Date: Fri, 29 Sep 2023 15:28:24 -0600 Subject: [PATCH 6/7] Update axum/src/json.rs Co-authored-by: Jonas Platte --- axum/src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/src/json.rs b/axum/src/json.rs index 69ac22f899..ebff242dd4 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -147,7 +147,7 @@ impl Json where T: DeserializeOwned, { - /// Construct a `Json` from `&Bytes`. Most users should prefer to use the `FromRequest` impl + /// Construct a `Json` from a byte slice. Most users should prefer to use the `FromRequest` impl /// but special cases may require first extracting a `Request` into `Bytes` then optionally /// constructing a `Json`. pub fn from_bytes(bytes: &[u8]) -> Result { From a3619b70d1e229e6291f91d54e605ec981af60cd Mon Sep 17 00:00:00 2001 From: wayne warren Date: Sun, 1 Oct 2023 05:33:00 -0600 Subject: [PATCH 7/7] update Changelog Signed-off-by: wayne warren --- axum/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md index 57474c5303..a2e4f94b92 100644 --- a/axum/CHANGELOG.md +++ b/axum/CHANGELOG.md @@ -66,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **added:** Implement `IntoResponse` for `(R,) where R: IntoResponse` ([#2143]) - **changed:** For SSE, add space between field and value for compatibility ([#2149]) - **added:** Add `NestedPath` extractor ([#1924]) +- **added:** Add `axum::Json::from_bytes` ([#2244]) [#1664]: https://github.com/tokio-rs/axum/pull/1664 [#1751]: https://github.com/tokio-rs/axum/pull/1751 @@ -86,6 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2140]: https://github.com/tokio-rs/axum/pull/2140 [#2143]: https://github.com/tokio-rs/axum/pull/2143 [#2149]: https://github.com/tokio-rs/axum/pull/2149 +[#2244]: https://github.com/tokio-rs/axum/pull/2244 # 0.6.17 (25. April, 2023)