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}