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 BearerCredential, BuildError, HttpsEndpoint, RawHyperClient, RequestTimeouts, UserAgent,
9 platform_client_config,
10};
11
12use super::{AsyncClient, RawAsyncClient};
13
14pub struct AsyncClientBuilder {
17 endpoint: HttpsEndpoint,
18 credential: BearerCredential,
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 credential: BearerCredential,
36 user_agent: UserAgent,
37 timeouts: RequestTimeouts,
38 ) -> Self {
39 Self {
40 endpoint,
41 credential,
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 if !self.credential.scope.matches_endpoint(&self.endpoint) {
58 return Err(BuildError::CredentialEndpointMismatch);
59 }
60 let client = configured_client(&self.user_agent, self.timeouts, https_only)?;
61 Ok(AsyncClient::new(
62 client,
63 self.endpoint,
64 self.credential,
65 !https_only,
66 ))
67 }
68
69 #[cfg(test)]
70 pub(super) fn build_for_loopback(self) -> Result<AsyncClient, BuildError> {
71 self.build_inner(false)
72 }
73}
74
75impl RawAsyncClientBuilder {
76 #[must_use]
78 pub const fn new(
79 endpoint: HttpsEndpoint,
80 user_agent: UserAgent,
81 timeouts: RequestTimeouts,
82 ) -> Self {
83 Self {
84 endpoint,
85 user_agent,
86 timeouts,
87 }
88 }
89
90 pub fn build(self) -> Result<RawAsyncClient, BuildError> {
92 self.build_inner(true)
93 }
94
95 fn build_inner(self, https_only: bool) -> Result<RawAsyncClient, BuildError> {
96 let tls_config = platform_client_config()?;
97 let client = RawHyperClient::new(
98 self.endpoint.clone(),
99 &self.user_agent,
100 self.timeouts,
101 tls_config,
102 https_only,
103 )?;
104 Ok(RawAsyncClient::new(client, self.endpoint))
105 }
106
107 #[cfg(test)]
108 pub(super) fn build_for_loopback(self) -> Result<RawAsyncClient, BuildError> {
109 self.build_inner(false)
110 }
111}
112
113impl fmt::Debug for AsyncClientBuilder {
114 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
115 formatter
116 .debug_struct("AsyncClientBuilder")
117 .field("endpoint", &"[redacted]")
118 .field("credential", &"[redacted]")
119 .field("user_agent", &self.user_agent)
120 .field("timeouts", &self.timeouts)
121 .finish()
122 }
123}
124
125impl fmt::Debug for RawAsyncClientBuilder {
126 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
127 formatter
128 .debug_struct("RawAsyncClientBuilder")
129 .field("endpoint", &"[redacted]")
130 .field("user_agent", &self.user_agent)
131 .field("timeouts", &self.timeouts)
132 .finish()
133 }
134}
135
136fn configured_client(
137 user_agent: &UserAgent,
138 timeouts: RequestTimeouts,
139 https_only: bool,
140) -> Result<Client, BuildError> {
141 Client::builder()
142 .tls_backend_rustls()
143 .https_only(https_only)
144 .http1_only()
145 .no_hickory_dns()
146 .min_tls_version(Version::TLS_1_2)
147 .redirect(Policy::none())
148 .retry(reqwest::retry::never())
149 .referer(false)
150 .no_proxy()
151 .no_gzip()
152 .no_brotli()
153 .no_zstd()
154 .no_deflate()
155 .timeout(timeouts.total())
156 .connect_timeout(timeouts.connect())
157 .connection_verbose(false)
158 .user_agent(user_agent.value.clone())
159 .build()
160 .map_err(|_| BuildError::ClientBuildFailed)
161}