cloud_sdk_reqwest/asynchronous/
config.rs1use core::fmt;
2
3use reqwest::Client;
4use reqwest::redirect::Policy;
5use reqwest::tls::Version;
6
7use crate::shared::{
8 BearerToken, BuildError, HttpsEndpoint, RawHyperClient, RequestTimeouts, UserAgent,
9 platform_client_config,
10};
11
12use super::{AsyncClient, RawAsyncClient};
13
14pub struct AsyncClientBuilder {
17 endpoint: HttpsEndpoint,
18 token: BearerToken,
19 user_agent: UserAgent,
20 timeouts: RequestTimeouts,
21}
22
23pub struct RawAsyncClientBuilder {
25 endpoint: HttpsEndpoint,
26 user_agent: UserAgent,
27 timeouts: RequestTimeouts,
28}
29
30impl AsyncClientBuilder {
31 #[must_use]
33 pub const fn new(
34 endpoint: HttpsEndpoint,
35 token: BearerToken,
36 user_agent: UserAgent,
37 timeouts: RequestTimeouts,
38 ) -> Self {
39 Self {
40 endpoint,
41 token,
42 user_agent,
43 timeouts,
44 }
45 }
46
47 pub fn build(self) -> Result<AsyncClient, BuildError> {
53 self.build_inner(true)
54 }
55
56 fn build_inner(self, https_only: bool) -> Result<AsyncClient, BuildError> {
57 let client = configured_client(&self.user_agent, self.timeouts, https_only)?;
58 Ok(AsyncClient::new(client, self.endpoint, self.token))
59 }
60
61 #[cfg(test)]
62 pub(super) fn build_for_loopback(self) -> Result<AsyncClient, BuildError> {
63 self.build_inner(false)
64 }
65}
66
67impl RawAsyncClientBuilder {
68 #[must_use]
70 pub const fn new(
71 endpoint: HttpsEndpoint,
72 user_agent: UserAgent,
73 timeouts: RequestTimeouts,
74 ) -> Self {
75 Self {
76 endpoint,
77 user_agent,
78 timeouts,
79 }
80 }
81
82 pub fn build(self) -> Result<RawAsyncClient, BuildError> {
84 self.build_inner(true)
85 }
86
87 fn build_inner(self, https_only: bool) -> Result<RawAsyncClient, BuildError> {
88 let tls_config = platform_client_config()?;
89 let client = RawHyperClient::new(
90 self.endpoint.clone(),
91 &self.user_agent,
92 self.timeouts,
93 tls_config,
94 https_only,
95 )?;
96 Ok(RawAsyncClient::new(client, self.endpoint))
97 }
98
99 #[cfg(test)]
100 pub(super) fn build_for_loopback(self) -> Result<RawAsyncClient, BuildError> {
101 self.build_inner(false)
102 }
103}
104
105impl fmt::Debug for AsyncClientBuilder {
106 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
107 formatter
108 .debug_struct("AsyncClientBuilder")
109 .field("endpoint", &"[redacted]")
110 .field("token", &"[redacted]")
111 .field("user_agent", &self.user_agent)
112 .field("timeouts", &self.timeouts)
113 .finish()
114 }
115}
116
117impl fmt::Debug for RawAsyncClientBuilder {
118 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
119 formatter
120 .debug_struct("RawAsyncClientBuilder")
121 .field("endpoint", &"[redacted]")
122 .field("user_agent", &self.user_agent)
123 .field("timeouts", &self.timeouts)
124 .finish()
125 }
126}
127
128fn configured_client(
129 user_agent: &UserAgent,
130 timeouts: RequestTimeouts,
131 https_only: bool,
132) -> Result<Client, BuildError> {
133 Client::builder()
134 .tls_backend_rustls()
135 .https_only(https_only)
136 .http1_only()
137 .no_hickory_dns()
138 .min_tls_version(Version::TLS_1_2)
139 .redirect(Policy::none())
140 .retry(reqwest::retry::never())
141 .referer(false)
142 .no_proxy()
143 .no_gzip()
144 .no_brotli()
145 .no_zstd()
146 .no_deflate()
147 .timeout(timeouts.total())
148 .connect_timeout(timeouts.connect())
149 .connection_verbose(false)
150 .user_agent(user_agent.value.clone())
151 .build()
152 .map_err(|_| BuildError::ClientBuildFailed)
153}