From fd141ef9b109c11ba6fb7007b261364037608ed8 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 16 Mar 2019 22:10:15 -0700 Subject: [PATCH] move json to actix-web --- src/httpmessage.rs | 40 -------- src/json.rs | 222 --------------------------------------------- src/lib.rs | 2 - 3 files changed, 264 deletions(-) delete mode 100644 src/json.rs diff --git a/src/httpmessage.rs b/src/httpmessage.rs index 3c049c09b..8573e917d 100644 --- a/src/httpmessage.rs +++ b/src/httpmessage.rs @@ -19,7 +19,6 @@ use crate::error::{ }; use crate::extensions::Extensions; use crate::header::Header; -use crate::json::JsonBody; use crate::payload::Payload; struct Cookies(Vec>); @@ -219,45 +218,6 @@ pub trait HttpMessage: Sized { UrlEncoded::new(self) } - /// Parse `application/json` encoded body. - /// Return `JsonBody` future. It resolves to a `T` value. - /// - /// Returns error: - /// - /// * content type is not `application/json` - /// * content length is greater than 256k - /// - /// ## Server example - /// - /// ```rust,ignore - /// # extern crate actix_web; - /// # extern crate futures; - /// # #[macro_use] extern crate serde_derive; - /// use actix_web::*; - /// use futures::future::{ok, Future}; - /// - /// #[derive(Deserialize, Debug)] - /// struct MyObj { - /// name: String, - /// } - /// - /// fn index(mut req: HttpRequest) -> Box> { - /// req.json() // <- get JsonBody future - /// .from_err() - /// .and_then(|val: MyObj| { // <- deserialized value - /// println!("==== BODY ==== {:?}", val); - /// Ok(Response::Ok().into()) - /// }).responder() - /// } - /// # fn main() {} - /// ``` - fn json(&mut self) -> JsonBody - where - Self::Stream: Stream + 'static, - { - JsonBody::new(self) - } - /// Return stream of lines. fn readlines(&mut self) -> Readlines where diff --git a/src/json.rs b/src/json.rs deleted file mode 100644 index 026ecb871..000000000 --- a/src/json.rs +++ /dev/null @@ -1,222 +0,0 @@ -use bytes::BytesMut; -use futures::{Future, Poll, Stream}; -use http::header::CONTENT_LENGTH; - -use bytes::Bytes; -use mime; -use serde::de::DeserializeOwned; -use serde_json; - -use crate::error::{JsonPayloadError, PayloadError}; -use crate::httpmessage::HttpMessage; -use crate::payload::Payload; - -/// Request payload json parser that resolves to a deserialized `T` value. -/// -/// Returns error: -/// -/// * content type is not `application/json` -/// * content length is greater than 256k -/// -/// # Server example -/// -/// ```rust,ignore -/// # extern crate actix_web; -/// # extern crate futures; -/// # #[macro_use] extern crate serde_derive; -/// use actix_web::{AsyncResponder, Error, HttpMessage, HttpRequest, Response}; -/// use futures::future::Future; -/// -/// #[derive(Deserialize, Debug)] -/// struct MyObj { -/// name: String, -/// } -/// -/// fn index(mut req: HttpRequest) -> Box> { -/// req.json() // <- get JsonBody future -/// .from_err() -/// .and_then(|val: MyObj| { // <- deserialized value -/// println!("==== BODY ==== {:?}", val); -/// Ok(Response::Ok().into()) -/// }).responder() -/// } -/// # fn main() {} -/// ``` -pub struct JsonBody { - limit: usize, - length: Option, - stream: Payload, - err: Option, - fut: Option>>, -} - -impl JsonBody -where - T: HttpMessage, - T::Stream: Stream + 'static, - U: DeserializeOwned + 'static, -{ - /// Create `JsonBody` for request. - pub fn new(req: &mut T) -> Self { - // check content-type - let json = if let Ok(Some(mime)) = req.mime_type() { - mime.subtype() == mime::JSON || mime.suffix() == Some(mime::JSON) - } else { - false - }; - if !json { - return JsonBody { - limit: 262_144, - length: None, - stream: Payload::None, - fut: None, - err: Some(JsonPayloadError::ContentType), - }; - } - - let mut len = None; - if let Some(l) = req.headers().get(CONTENT_LENGTH) { - if let Ok(s) = l.to_str() { - if let Ok(l) = s.parse::() { - len = Some(l) - } - } - } - - JsonBody { - limit: 262_144, - length: len, - stream: req.take_payload(), - fut: None, - err: None, - } - } - - /// Change max size of payload. By default max size is 256Kb - pub fn limit(mut self, limit: usize) -> Self { - self.limit = limit; - self - } -} - -impl Future for JsonBody -where - T: HttpMessage, - T::Stream: Stream + 'static, - U: DeserializeOwned + 'static, -{ - type Item = U; - type Error = JsonPayloadError; - - fn poll(&mut self) -> Poll { - if let Some(ref mut fut) = self.fut { - return fut.poll(); - } - - if let Some(err) = self.err.take() { - return Err(err); - } - - let limit = self.limit; - if let Some(len) = self.length.take() { - if len > limit { - return Err(JsonPayloadError::Overflow); - } - } - - let fut = std::mem::replace(&mut self.stream, Payload::None) - .from_err() - .fold(BytesMut::with_capacity(8192), move |mut body, chunk| { - if (body.len() + chunk.len()) > limit { - Err(JsonPayloadError::Overflow) - } else { - body.extend_from_slice(&chunk); - Ok(body) - } - }) - .and_then(|body| Ok(serde_json::from_slice::(&body)?)); - self.fut = Some(Box::new(fut)); - self.poll() - } -} - -#[cfg(test)] -mod tests { - use bytes::Bytes; - use futures::Async; - use http::header; - use serde_derive::{Deserialize, Serialize}; - - use super::*; - use crate::test::TestRequest; - - impl PartialEq for JsonPayloadError { - fn eq(&self, other: &JsonPayloadError) -> bool { - match *self { - JsonPayloadError::Overflow => match *other { - JsonPayloadError::Overflow => true, - _ => false, - }, - JsonPayloadError::ContentType => match *other { - JsonPayloadError::ContentType => true, - _ => false, - }, - _ => false, - } - } - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct MyObject { - name: String, - } - - #[test] - fn test_json_body() { - let mut req = TestRequest::default().finish(); - let mut json = req.json::(); - assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType); - - let mut req = TestRequest::default() - .header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("application/text"), - ) - .finish(); - let mut json = req.json::(); - assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType); - - let mut req = TestRequest::default() - .header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("application/json"), - ) - .header( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("10000"), - ) - .finish(); - let mut json = req.json::().limit(100); - assert_eq!(json.poll().err().unwrap(), JsonPayloadError::Overflow); - - let mut req = TestRequest::default() - .header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("application/json"), - ) - .header( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("16"), - ) - .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) - .finish(); - - let mut json = req.json::(); - assert_eq!( - json.poll().ok().unwrap(), - Async::Ready(MyObject { - name: "test".to_owned() - }) - ); - } -} diff --git a/src/lib.rs b/src/lib.rs index 41ee55fec..443266a9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,7 +77,6 @@ mod header; mod helpers; mod httpcodes; pub mod httpmessage; -mod json; mod message; mod payload; mod request; @@ -113,7 +112,6 @@ pub mod dev { //! ``` pub use crate::httpmessage::{MessageBody, Readlines, UrlEncoded}; - pub use crate::json::JsonBody; pub use crate::response::ResponseBuilder; }