diff options
-rw-r--r-- | Cargo.toml | 12 | ||||
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/request.rs | 23 |
3 files changed, 36 insertions, 2 deletions
@@ -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 @@ -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}")] |