diff --git a/src/async_impl/response.rs b/src/async_impl/response.rs index fc5a5d464..7fb3d28c0 100644 --- a/src/async_impl/response.rs +++ b/src/async_impl/response.rs @@ -240,6 +240,56 @@ impl Response { serde_json::from_slice(&full).map_err(crate::error::decode) } + /// Try to deserialize a single chunk of the request body as JSON. + /// + /// When the response body has been exhausted, this will return `Ok(None)`. + /// + /// # Optional + /// + /// This requires the optional `json` feature enabled. + /// + /// # Example + /// + /// ```rust + /// # extern crate reqwest; + /// # extern crate serde; + /// # + /// # use reqwest::Error; + /// # use serde::Deserialize; + /// # + /// // This `derive` requires the `serde` dependency. + /// #[derive(Deserialize)] + /// struct Ip { + /// origin: String, + /// } + /// + /// # async fn run() -> Result<(), Error> { + /// let mut res = reqwest::get("http://httpbin.org/ip").await?; + /// + /// while let Some(chunk) = res.json_chunk::().await? { + /// println!("Chunk: {:?}", chunk); + /// } + /// # Ok(()) + /// # } + /// ``` + /// + /// # Errors + /// + /// This method fails whenever the response chunk is not in JSON format + /// or it cannot be properly deserialized to target type `T`. For more + /// details please see [`serde_json::from_reader`]. + /// + /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html + #[cfg(feature = "json")] + #[cfg_attr(docsrs, doc(cfg(feature = "json")))] + pub async fn json_chunk(&mut self) -> crate::Result> { + if let Some(full) = self.chunk().await? { + Ok(Some(serde_json::from_slice(&full).map_err(crate::error::decode)?)) + } else { + Ok(None) + } + } + /// Get the full response body as `Bytes`. /// /// # Example diff --git a/src/blocking/response.rs b/src/blocking/response.rs index 8d0e9b9cf..a0ddb2c16 100644 --- a/src/blocking/response.rs +++ b/src/blocking/response.rs @@ -244,6 +244,55 @@ impl Response { }) } + /// Try to deserialize a single chunk of the request body as JSON. + /// + /// When the response body has been exhausted, this will return `Ok(None)`. + /// + /// # Optional + /// + /// This requires the optional `json` feature enabled. + /// + /// # Example + /// + /// ```rust + /// # extern crate reqwest; + /// # extern crate serde; + /// # + /// # use reqwest::Error; + /// # use serde::Deserialize; + /// # + /// // This `derive` requires the `serde` dependency. + /// #[derive(Deserialize)] + /// struct Ip { + /// origin: String, + /// } + /// + /// # fn run() -> Result<(), Error> { + /// let mut res = reqwest::blocking::get("http://httpbin.org/ip")?; + /// + /// while let Some(chunk) = res.json_chunk::()? { + /// println!("Chunk: {:?}", chunk); + /// } + /// # Ok(()) + /// # } + /// ``` + /// + /// # Errors + /// + /// This method fails whenever the response chunk is not in JSON format + /// or it cannot be properly deserialized to target type `T`. For more + /// details please see [`serde_json::from_reader`]. + /// + /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html + #[cfg(feature = "json")] + #[cfg_attr(docsrs, doc(cfg(feature = "json")))] + pub fn json_chunk(&mut self) -> crate::Result> { + wait::timeout(self.inner.json_chunk(), self.timeout).map_err(|e| match e { + wait::Waited::TimedOut(e) => crate::error::decode(e), + wait::Waited::Inner(e) => e, + }) + } + /// Get the full response body as `Bytes`. /// /// # Example @@ -263,6 +312,29 @@ impl Response { }) } + /// Stream a chunk of the response body. + /// + /// When the response body has been exhausted, this will return `None`. + /// + /// # Example + /// + /// ``` + /// # fn run() -> Result<(), Box> { + /// let mut res = reqwest::blocking::get("https://hyper.rs")?; + /// + /// while let Some(chunk) = res.chunk()? { + /// println!("Chunk: {:?}", chunk); + /// } + /// # Ok(()) + /// # } + /// ``` + pub fn chunk(&mut self) -> crate::Result> { + wait::timeout(self.inner.chunk(), self.timeout).map_err(|e| match e { + wait::Waited::TimedOut(e) => crate::error::decode(e), + wait::Waited::Inner(e) => e, + }) + } + /// Get the response text. /// /// This method decodes the response body with BOM sniffing