Skip to content

Commit

Permalink
WASM: Add try_clone implementations to Request and `RequestBuilde…
Browse files Browse the repository at this point in the history
…r` (#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.
  • Loading branch information
kjvalencik committed Jun 14, 2021
1 parent b48cb4a commit c4388fc
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/wasm/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct Body {
inner: Inner,
}

#[derive(Clone)]
enum Inner {
Bytes(Bytes),
#[cfg(feature = "multipart")]
Expand Down Expand Up @@ -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<Bytes> for Body {
Expand Down
45 changes: 45 additions & 0 deletions src/wasm/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ impl Request {
pub fn body_mut(&mut self) -> &mut Option<Body> {
&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<Request> {
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 {
Expand Down Expand Up @@ -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<RequestBuilder> {
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 {
Expand Down

0 comments on commit c4388fc

Please sign in to comment.