From c4388fcff9401d23169c6731901457e89039bf53 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 14 Jun 2021 13:36:56 -0400 Subject: [PATCH] WASM: Add `try_clone` implementations to `Request` and `RequestBuilder` (#1286) Currently the wasm client does not implement `try_clone` on `Request` or `RequestBuilder` like the blocking and async clients. This PR adds infallible `try_clone` implementations to the wasm client to improve the API parity. *Note*: Even though these APIs are infallible on wasm (no streaming bodies), I chose to keep the API identical. --- src/wasm/body.rs | 7 +++++++ src/wasm/request.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/wasm/body.rs b/src/wasm/body.rs index ed6af86..d67f510 100644 --- a/src/wasm/body.rs +++ b/src/wasm/body.rs @@ -17,6 +17,7 @@ pub struct Body { inner: Inner, } +#[derive(Clone)] enum Inner { Bytes(Bytes), #[cfg(feature = "multipart")] @@ -56,6 +57,12 @@ impl Body { Inner::Multipart(form) => form.is_empty(), } } + + pub(crate) fn clone(&self) -> Body { + Self { + inner: self.inner.clone(), + } + } } impl From for Body { diff --git a/src/wasm/request.rs b/src/wasm/request.rs index 35d0360..40bb37b 100644 --- a/src/wasm/request.rs +++ b/src/wasm/request.rs @@ -89,6 +89,21 @@ impl Request { pub fn body_mut(&mut self) -> &mut Option { &mut self.body } + + /// Attempts to clone the `Request`. + /// + /// None is returned if a body is which can not be cloned. This method + /// currently always returns `Some`, but that may change in the future. + pub fn try_clone(&self) -> Option { + Some(Self { + method: self.method.clone(), + url: self.url.clone(), + headers: self.headers.clone(), + body: self.body.as_ref().map(|body| body.clone()), + cors: self.cors, + credentials: self.credentials.clone(), + }) + } } impl RequestBuilder { @@ -335,6 +350,36 @@ impl RequestBuilder { let req = self.request?; self.client.execute_request(req).await } + + /// Attempt to clone the RequestBuilder. + /// + /// `None` is returned if the RequestBuilder can not be cloned. This method + /// currently always returns `Some`, but that may change in the future. + /// + /// # Examples + /// + /// ```no_run + /// # use reqwest::Error; + /// # + /// # fn run() -> Result<(), Error> { + /// let client = reqwest::Client::new(); + /// let builder = client.post("http://httpbin.org/post") + /// .body("from a &str!"); + /// let clone = builder.try_clone(); + /// assert!(clone.is_some()); + /// # Ok(()) + /// # } + /// ``` + pub fn try_clone(&self) -> Option { + self.request + .as_ref() + .ok() + .and_then(|req| req.try_clone()) + .map(|req| RequestBuilder { + client: self.client.clone(), + request: Ok(req), + }) + } } impl fmt::Debug for Request {