aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hyper_body.rs64
-rw-r--r--src/lib.rs10
-rw-r--r--src/request.rs66
-rw-r--r--src/response.rs10
4 files changed, 80 insertions, 70 deletions
diff --git a/src/hyper_body.rs b/src/hyper_body.rs
new file mode 100644
index 0000000..c6824fb
--- /dev/null
+++ b/src/hyper_body.rs
@@ -0,0 +1,64 @@
+//! Extends `hyper::Body` with [`SputnikBody`].
+use hyper::http::{self, response::Builder};
+use async_trait::async_trait;
+use serde::de::DeserializeOwned;
+
+use crate::response::EmptyBuilder;
+
+impl EmptyBuilder<hyper::Body> for Builder {
+ fn empty(self) -> http::Result<http::response::Response<hyper::Body>> {
+ self.body(hyper::Body::empty())
+ }
+}
+
+/// Adds deserialization methods to [`hyper::Body`].
+#[async_trait]
+pub trait SputnikBody {
+ /// Parses a `application/x-www-form-urlencoded` request body into a given struct.
+ async fn into_form<T: DeserializeOwned>(self) -> Result<T, FormError>;
+
+ /// Attempts to deserialize the request body as JSON.
+ #[cfg(feature = "hyper_body_json")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "hyper_body_json")))]
+ async fn into_json<T: DeserializeOwned>(self) -> Result<T, JsonError>;
+}
+
+#[async_trait]
+impl SputnikBody for hyper::Body {
+
+ async fn into_form<T: DeserializeOwned>(self) -> Result<T, FormError> {
+ let full_body = hyper::body::to_bytes(self).await.map_err(BodyError)?;
+ Ok(serde_urlencoded::from_bytes::<T>(&full_body)?)
+ }
+
+ #[cfg(feature = "hyper_body_json")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "hyper_body_json")))]
+ async fn into_json<T: DeserializeOwned>(self) -> Result<T, JsonError> {
+ let full_body = hyper::body::to_bytes(self).await.map_err(BodyError)?;
+ Ok(serde_json::from_slice::<T>(&full_body)?)
+ }
+}
+
+#[derive(thiserror::Error, Debug)]
+#[error("failed to read body")]
+pub struct BodyError(pub hyper::Error);
+
+#[derive(thiserror::Error, Debug)]
+pub enum FormError {
+ #[error("{0}")]
+ Body(#[from] BodyError),
+
+ #[error("form deserialize error: {0}")]
+ Deserialize(#[from] serde_urlencoded::de::Error),
+}
+
+#[cfg(feature = "hyper_body_json")]
+#[cfg_attr(docsrs, doc(cfg(feature = "hyper_body_json")))]
+#[derive(thiserror::Error, Debug)]
+pub enum JsonError {
+ #[error("{0}")]
+ Body(#[from] BodyError),
+
+ #[error("json deserialize error: {0}")]
+ Deserialize(#[from] serde_json::Error),
+} \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 2f30028..760acf1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,4 +9,12 @@ pub use httpdate;
pub mod security;
pub mod request;
pub mod response;
-mod signed; \ No newline at end of file
+mod signed;
+#[cfg(feature="hyper_body")]
+#[cfg_attr(docsrs, doc(cfg(feature = "hyper_body")))]
+pub mod hyper_body;
+
+#[cfg(not(feature="hyper_body"))]
+use http;
+#[cfg(feature="hyper_body")]
+use hyper::http; \ No newline at end of file
diff --git a/src/request.rs b/src/request.rs
index 95f5a32..6efacc9 100644
--- a/src/request.rs
+++ b/src/request.rs
@@ -1,14 +1,13 @@
-//! Provides the [`SputnikParts`] and [`SputnikBody`] traits.
+//! Provides the [`SputnikParts`] trait.
use cookie::Cookie;
use mime::Mime;
use serde::de::DeserializeOwned;
-use hyper::{HeaderMap, body::Bytes, header, http::request::Parts};
use time::Duration;
use std::{collections::HashMap, sync::Arc};
-use async_trait::async_trait;
use crate::response::{SputnikHeaders, delete_cookie};
+use crate::http::{HeaderMap, header, request::Parts};
/// Adds convenience methods to [`http::request::Parts`](Parts).
pub trait SputnikParts {
@@ -22,7 +21,7 @@ pub trait SputnikParts {
fn enforce_content_type(&self, mime: Mime) -> Result<(), WrongContentTypeError>;
/// A map of response headers to allow methods of this trait to set response
- /// headers without needing to take a [`Response`](hyper::http::response::Response) as an argument.
+ /// headers without needing to take a [`Response`](crate::http::response::Response) as an argument.
///
/// You need to take care to append these headers to the response yourself.
/// This is intended to be done after your routing logic so that your
@@ -137,85 +136,30 @@ impl Flash {
}
}
-/// Adds deserialization methods to [`hyper::Body`].
-#[async_trait]
-pub trait SputnikBody {
- async fn into_bytes(self) -> Result<Bytes, BodyError>;
-
- /// Parses a `application/x-www-form-urlencoded` request body into a given struct.
- async fn into_form<T: DeserializeOwned>(self) -> Result<T, FormError>;
-
- /// 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>;
-}
-
-#[async_trait]
-impl SputnikBody for hyper::Body {
- async fn into_bytes(self) -> Result<Bytes, BodyError> {
- hyper::body::to_bytes(self).await.map_err(BodyError)
- }
-
- async fn into_form<T: DeserializeOwned>(self) -> Result<T, FormError> {
- let full_body = self.into_bytes().await?;
- Ok(serde_urlencoded::from_bytes::<T>(&full_body)?)
- }
-
- #[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(thiserror::Error, Debug)]
#[error("query deserialize error: {0}")]
pub struct QueryError(pub serde_urlencoded::de::Error);
#[derive(thiserror::Error, Debug)]
-#[error("failed to read body")]
-pub struct BodyError(pub hyper::Error);
-
-#[derive(thiserror::Error, Debug)]
#[error("expected Content-Type {expected} but received {}", received.as_ref().unwrap_or(&"nothing".to_owned()))]
pub struct WrongContentTypeError {
pub expected: Mime,
pub received: Option<String>,
}
-#[derive(thiserror::Error, Debug)]
-pub enum FormError {
- #[error("{0}")]
- Body(#[from] BodyError),
-
- #[error("form deserialize error: {0}")]
- 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),
-}
#[cfg(test)]
mod tests {
use std::convert::TryInto;
- use hyper::{Request, header};
+ use crate::http::{Request, header};
use super::SputnikParts;
#[test]
fn test_enforce_content_type() {
- let (mut parts, _body) = Request::new(hyper::Body::empty()).into_parts();
+ let (mut parts, _body) = Request::new("").into_parts();
assert!(parts.enforce_content_type(mime::APPLICATION_JSON).is_err());
parts.headers.append(header::CONTENT_TYPE, "application/json".try_into().unwrap());
diff --git a/src/response.rs b/src/response.rs
index 2d5d469..cb87a80 100644
--- a/src/response.rs
+++ b/src/response.rs
@@ -3,9 +3,9 @@
use std::convert::TryInto;
use cookie::Cookie;
-use hyper::{HeaderMap, StatusCode, header, http};
use time::{Duration, OffsetDateTime};
-use hyper::http::response::Builder;
+
+use crate::http::{self, HeaderMap, StatusCode, header, response::Builder};
/// Adds convenience methods to [`Builder`].
pub trait SputnikBuilder {
@@ -66,12 +66,6 @@ pub trait EmptyBuilder<B> {
fn empty(self) -> http::Result<http::response::Response<B>>;
}
-impl EmptyBuilder<hyper::Body> for Builder {
- fn empty(self) -> http::Result<http::response::Response<hyper::Body>> {
- self.body(hyper::Body::empty())
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;