feat(net): mock request builder adds .with and .with_{option,result}
Support for specifying conditional clauses fluently.
This commit is contained in:
parent
5169da03dc
commit
ed590552c7
2 changed files with 189 additions and 3 deletions
|
@ -146,10 +146,8 @@ mod system;
|
|||
|
||||
pub use result::{Error, Result};
|
||||
|
||||
pub use system::{MockNet, Net};
|
||||
pub use system::{MockNet, Net, ReqBuilder, WithOption, WithResult};
|
||||
|
||||
pub use http::HeaderMap;
|
||||
pub use http::Method;
|
||||
pub use http::StatusCode;
|
||||
pub use reqwest::Client;
|
||||
pub use reqwest::Error as RequestError;
|
||||
|
|
|
@ -240,6 +240,102 @@ impl<'net> ReqBuilder<'net> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Use the function to modify the request in-line.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use kxio::net::Result;
|
||||
/// # async fn run() -> Result<()> {
|
||||
/// let net = kxio::net::new();
|
||||
/// let response= net
|
||||
/// .get("http://localhost/")
|
||||
/// .with(|request| add_std_headers(request))
|
||||
/// .send()
|
||||
/// .await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// fn add_std_headers(request: kxio::net::ReqBuilder) -> kxio::net::ReqBuilder {
|
||||
/// request
|
||||
/// .header("ClientVersion", "1.23.45")
|
||||
/// .header("Agent", "MyApp/1.1")
|
||||
/// }
|
||||
/// ````
|
||||
#[must_use]
|
||||
pub fn with(self, f: impl FnOnce(Self) -> Self) -> Self {
|
||||
f(self)
|
||||
}
|
||||
|
||||
/// Starts an Option clause for the supplied option.
|
||||
///
|
||||
/// Must be followed by [WithOption::some], [WithOption::none] or [WithOption::either]
|
||||
/// to resume the with the [ReqBuilder].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use kxio::net::Result;
|
||||
/// # async fn run() -> Result<()> {
|
||||
/// let net = kxio::net::new();
|
||||
/// let response= net
|
||||
/// .get("http://localhost/")
|
||||
/// .with_option(Some("value"))
|
||||
/// .some(|request, value| request.header("optional-header", value))
|
||||
/// .with_option(Some("value"))
|
||||
/// .none(|request| request.header("special-header", "not-found"))
|
||||
/// .with_option(Some("value"))
|
||||
/// .either(
|
||||
/// /* some */ |request, value| request.header("Setting", value),
|
||||
/// /* none */ |request| request.header("Setting", "missing")
|
||||
/// )
|
||||
/// .send()
|
||||
/// .await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn with_option<T>(self, option: Option<T>) -> WithOption<'net, T> {
|
||||
WithOption {
|
||||
req_builder: self,
|
||||
option,
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts a Result clause for the supplied result.
|
||||
///
|
||||
/// Must be followed by [WithResult::ok], [WithResult::err] or [WithResult::either]
|
||||
/// to resume the with the [ReqBuilder].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use kxio::net::Result;
|
||||
/// # async fn run() -> Result<()> {
|
||||
/// let net = kxio::net::new();
|
||||
/// let response = net
|
||||
/// .get("http://localhost/")
|
||||
/// .with_result::<&str, ()>(Ok("value"))
|
||||
/// .ok(|request, value| request.header("good-header", value))
|
||||
/// .with_result::<(), &str>(Err("value"))
|
||||
/// .err(|request, err| request.header("bad-header", err))
|
||||
/// .with_result::<&str, &str>(Ok("value"))
|
||||
/// .either(
|
||||
/// /* ok */ |request, ok| request.header("Setting", ok),
|
||||
/// /* err */ |request, err| request.header("SettingError", err)
|
||||
/// )
|
||||
/// .send()
|
||||
/// .await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn with_result<T, E>(self, result: std::result::Result<T, E>) -> WithResult<'net, T, E> {
|
||||
WithResult {
|
||||
req_builder: self,
|
||||
result,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs the Request and sends it to the target URL, returning a
|
||||
/// future Response.
|
||||
///
|
||||
|
@ -653,6 +749,98 @@ impl<'net> WhenRequest<'net, WhenBuildResponse> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Option clause for building a request with [ReqBuilder].
|
||||
///
|
||||
/// See: [ReqBuilder::with_option].
|
||||
pub struct WithOption<'net, T> {
|
||||
req_builder: ReqBuilder<'net>,
|
||||
option: Option<T>,
|
||||
}
|
||||
impl<'net, T> WithOption<'net, T> {
|
||||
/// Handles when the preceeding [Option] is [Some].
|
||||
///
|
||||
/// The function is passed the [ReqBuilder] and the value in the [Some].
|
||||
///
|
||||
/// Returns the [ReqBuilder].
|
||||
pub fn some(
|
||||
self,
|
||||
f_some: impl FnOnce(ReqBuilder<'net>, T) -> ReqBuilder<'net>,
|
||||
) -> ReqBuilder<'net> {
|
||||
match self.option {
|
||||
Some(value) => f_some(self.req_builder, value),
|
||||
None => self.req_builder,
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles when the preceeding [Option] is [None].
|
||||
///
|
||||
/// The function is passed the [ReqBuilder].
|
||||
///
|
||||
/// Returns the [ReqBuilder].
|
||||
pub fn none(
|
||||
self,
|
||||
f_none: impl FnOnce(ReqBuilder<'net>) -> ReqBuilder<'net>,
|
||||
) -> ReqBuilder<'net> {
|
||||
match self.option {
|
||||
None => f_none(self.req_builder),
|
||||
Some(_) => self.req_builder,
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles the preceeding [Option].
|
||||
///
|
||||
/// If the [Option] is [Some], then the `f_some` function is passed the [ReqBuilder] and the value in the [Some].
|
||||
///
|
||||
/// If the [Option] is [None], then the `f_none` function is passed the [ReqBuilder].
|
||||
///
|
||||
/// Returns the [ReqBuilder].
|
||||
pub fn either(
|
||||
self,
|
||||
f_some: impl FnOnce(ReqBuilder<'net>, T) -> ReqBuilder<'net>,
|
||||
f_none: impl FnOnce(ReqBuilder<'net>) -> ReqBuilder<'net>,
|
||||
) -> ReqBuilder<'net> {
|
||||
match self.option {
|
||||
Some(value) => f_some(self.req_builder, value),
|
||||
None => f_none(self.req_builder),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WithResult<'net, T, E> {
|
||||
req_builder: ReqBuilder<'net>,
|
||||
result: std::result::Result<T, E>,
|
||||
}
|
||||
impl<'net, T, E> WithResult<'net, T, E> {
|
||||
pub fn ok(
|
||||
self,
|
||||
f_ok: impl FnOnce(ReqBuilder<'net>, T) -> ReqBuilder<'net>,
|
||||
) -> ReqBuilder<'net> {
|
||||
match self.result {
|
||||
Ok(ok) => f_ok(self.req_builder, ok),
|
||||
Err(_) => self.req_builder,
|
||||
}
|
||||
}
|
||||
pub fn err(
|
||||
self,
|
||||
f_err: impl FnOnce(ReqBuilder<'net>, E) -> ReqBuilder<'net>,
|
||||
) -> ReqBuilder<'net> {
|
||||
match self.result {
|
||||
Err(err) => f_err(self.req_builder, err),
|
||||
Ok(_) => self.req_builder,
|
||||
}
|
||||
}
|
||||
pub fn either(
|
||||
self,
|
||||
f_ok: impl FnOnce(ReqBuilder<'net>, T) -> ReqBuilder<'net>,
|
||||
f_err: impl FnOnce(ReqBuilder<'net>, E) -> ReqBuilder<'net>,
|
||||
) -> ReqBuilder<'net> {
|
||||
match self.result {
|
||||
Ok(ok) => f_ok(self.req_builder, ok),
|
||||
Err(err) => f_err(self.req_builder, err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in a new issue