aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-01-25 16:56:08 +0100
committerMartin Fischer <martin@push-f.com>2021-01-25 16:59:00 +0100
commite04c832200f38ab49ce8e7a6d08ffc549b8a98e2 (patch)
treee3a5e090a7794580bb2899a9c862b19761249deb
parent9fa7442e41bc11ab3d62f43f5f6e90b59e160da2 (diff)
introduce optional SputnikBody::into_json()
bump version to 0.3.2
-rw-r--r--Cargo.toml12
-rw-r--r--src/lib.rs3
-rw-r--r--src/request.rs23
3 files changed, 36 insertions, 2 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 6925869..1efc0de 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "sputnik"
-version = "0.3.1"
+version = "0.3.2"
authors = ["Martin Fischer <martin@push-f.com>"]
license = "MIT"
description = "A lightweight layer on top of hyper to facilitate building web applications."
@@ -11,6 +11,9 @@ keywords = ["hyper", "web", "cookie", "csrf", "hmac"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[features]
+json = ["serde_json"]
+
[dependencies]
hyper = "0.13"
cookie = { version = "0.14", features = ["percent-encode"] }
@@ -24,4 +27,9 @@ rand = "0.7.3"
sha2 = "0.9"
time = "0.2"
thiserror = "1.0"
-async-trait = "0.1.42" \ No newline at end of file
+async-trait = "0.1.42"
+serde_json = { version = "1.0.61", optional = true }
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"] \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 0841e0b..2f30028 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,8 @@
//! A lightweight layer on top of [Hyper](https://hyper.rs/)
//! to facilitate building web applications.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+
pub use mime;
pub use httpdate;
diff --git a/src/request.rs b/src/request.rs
index 509e2e7..5b5679d 100644
--- a/src/request.rs
+++ b/src/request.rs
@@ -96,6 +96,11 @@ pub trait SputnikBody {
///
/// The HTML form must embed a hidden input generated with [`crate::request::SputnikParts::csrf_html_input`].
async fn into_form_csrf<T: DeserializeOwned>(self, req: &mut Parts) -> Result<T, CsrfProtectedFormError>;
+
+ /// Attempts to deserialize the request body as JSON.
+ #[cfg(feature = "json")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
+ async fn into_json<T: DeserializeOwned>(self) -> Result<T, JsonError>;
}
fn csrf_token_from_cookies(req: &mut Parts) -> Option<String> {
@@ -125,6 +130,13 @@ impl SputnikBody for hyper::Body {
None => Err(CsrfProtectedFormError::NoCookie)
}
}
+
+ #[cfg(feature = "json")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
+ async fn into_json<T: DeserializeOwned>(self) -> Result<T, JsonError> {
+ let full_body = self.into_bytes().await?;
+ Ok(serde_json::from_slice::<T>(&full_body)?)
+ }
}
#[derive(Deserialize)]
@@ -156,6 +168,17 @@ pub enum FormError {
Deserialize(#[from] serde_urlencoded::de::Error),
}
+#[cfg(feature = "json")]
+#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
+#[derive(thiserror::Error, Debug)]
+pub enum JsonError {
+ #[error("{0}")]
+ Body(#[from] BodyError),
+
+ #[error("json deserialize error: {0}")]
+ Deserialize(#[from] serde_json::Error),
+}
+
#[derive(thiserror::Error, Debug)]
pub enum CsrfProtectedFormError {
#[error("{0}")]