verity_client/
request.rs

1use std::convert::TryFrom;
2
3use http::{HeaderName, HeaderValue};
4use reqwest::{header::HeaderMap, Body, Request};
5use serde::Serialize;
6
7use crate::client::{VerityClient, VerityResponse};
8
9/// A builder to construct the properties of a `Request`.
10///
11/// To construct a `RequestBuilder`, refer to the `Client` documentation.
12#[must_use = "RequestBuilder does nothing until you 'send' it"]
13pub struct RequestBuilder {
14    pub(crate) client: VerityClient,
15    pub(crate) inner: reqwest::RequestBuilder,
16}
17
18impl RequestBuilder {
19    /// Add a `Header` to this Request.
20    ///
21    /// This method allows you to add a single header to the request.
22    pub fn header<K, V>(self, key: K, value: V) -> Self
23    where
24        HeaderName: TryFrom<K>,
25        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
26        HeaderValue: TryFrom<V>,
27        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
28    {
29        RequestBuilder {
30            inner: self.inner.header(key, value),
31            ..self
32        }
33    }
34
35    /// Add a set of Headers to the existing ones on this Request.
36    ///
37    /// This method merges the provided headers with any already set on the request.
38    pub fn headers(self, headers: HeaderMap) -> Self {
39        RequestBuilder {
40            inner: self.inner.headers(headers),
41            ..self
42        }
43    }
44
45    /// Set the request body.
46    ///
47    /// This method sets the body of the request to the provided value.
48    pub fn body<T: Into<Body>>(self, body: T) -> Self {
49        RequestBuilder {
50            inner: self.inner.body(body),
51            ..self
52        }
53    }
54
55    /// Send a JSON body.
56    ///
57    /// This method serializes the provided data structure as JSON and sets it as the request body.
58    ///
59    /// # Errors
60    ///
61    /// Serialization can fail if `T`'s implementation of `Serialize` decides to
62    /// fail, or if `T` contains a map with non-string keys.
63    pub fn json<T: Serialize + ?Sized>(self, json: &T) -> Self {
64        RequestBuilder {
65            inner: self.inner.json(json),
66            ..self
67        }
68    }
69
70    /// Add a Redact instruction.
71    ///
72    /// This method adds a header to instruct Verity Prover on how to hide sensitive data.
73    pub fn redact(self, redact: String) -> Self {
74        RequestBuilder {
75            inner: self
76                .inner
77                .header("T-REDACTED", HeaderValue::from_str(&redact).unwrap()),
78            ..self
79        }
80    }
81
82    /// Build a `Request`.
83    ///
84    /// This method constructs the request, which can then be
85    /// inspected, modified and executed with `VerityClient::execute()`.
86    pub fn build(self) -> reqwest::Result<Request> {
87        self.inner.build()
88    }
89
90    /// Build a `Request`, which can be inspected, modified and executed with
91    /// `VerityClient::execute()`.
92    ///
93    /// This is similar to [`RequestBuilder::build()`], but also returns the
94    /// embedded `VerityClient`.
95    pub fn build_split(self) -> (VerityClient, reqwest::Result<Request>) {
96        let Self { inner, client, .. } = self;
97        let (_, req) = inner.build_split();
98
99        (client, req)
100    }
101
102    /// Constructs the Request and sends it to the target URL, returning a
103    /// future Response.
104    ///
105    /// # Errors
106    ///
107    /// This method fails if there was an error while sending request,
108    /// redirect loop was detected or redirect limit was exhausted.
109    ///
110    /// # Example
111    ///
112    /// ```no_run
113    /// # use anyhow::Error;
114    /// # use verity_client::client::{VerityClient, VerityClientConfig};
115    /// # async fn run() -> Result<(), Error> {
116    ///
117    ///
118    /// let config = VerityClientConfig {
119    ///     prover_url: String::from("http://127.0.0.1:8080"),
120    /// };
121    ///
122    /// let response = VerityClient::new(config)
123    ///     .get("https://hyper.rs")
124    ///     .send()
125    ///     .await?;
126    /// # Ok(())
127    /// # }
128    /// ```
129    pub async fn send(self) -> anyhow::Result<VerityResponse> {
130        let (mut client, req) = self.build_split();
131        client.execute_request(req?).await
132    }
133}