cloud_sdk_reqwest/asynchronous/
basic_client.rs1use core::fmt;
2use std::sync::Arc;
3
4use cloud_sdk::authentication::{AsyncAuthenticatedTransport, AuthenticatedRequest};
5use cloud_sdk::transport::{
6 BoundTransport, EndpointIdentity, EndpointIdentityError, ResponseStorageSanitizer,
7 ResponseWriter,
8};
9use cloud_sdk_sanitization::sanitize_bytes;
10use reqwest::Client;
11
12use crate::shared::{
13 BasicCredential, HttpsEndpoint, TransportError, map_authentication_error,
14 validate_basic_authentication,
15};
16
17use super::client::execute;
18
19#[derive(Clone)]
21pub struct AsyncBasicClient {
22 client: Client,
23 endpoint: HttpsEndpoint,
24 credential: Arc<BasicCredential>,
25 allow_insecure_loopback: bool,
26}
27
28impl AsyncBasicClient {
29 pub(super) fn new(
30 client: Client,
31 endpoint: HttpsEndpoint,
32 credential: BasicCredential,
33 allow_insecure_loopback: bool,
34 ) -> Self {
35 Self {
36 client,
37 endpoint,
38 credential: Arc::new(credential),
39 allow_insecure_loopback,
40 }
41 }
42
43 async fn send_inner(
44 &self,
45 authenticated: AuthenticatedRequest<'_, '_>,
46 response: &mut ResponseWriter<'_>,
47 ) -> Result<(), TransportError> {
48 let mut response_attempt = response
49 .begin_attempt()
50 .map_err(|_| TransportError::ResponseCommitFailed)?;
51 let endpoint = self
52 .endpoint
53 .identity()
54 .map_err(|_| TransportError::AuthenticationEndpointMismatch)?;
55 validate_basic_authentication(
56 endpoint,
57 self.credential.scope(),
58 authenticated.policy(),
59 self.allow_insecure_loopback,
60 )
61 .map_err(map_authentication_error)?;
62 let authorization = self
63 .credential
64 .header_value()
65 .map_err(|_| TransportError::HeaderRejected)?;
66 execute(
67 &self.client,
68 &self.endpoint,
69 authorization,
70 authenticated,
71 &mut response_attempt,
72 )
73 .await
74 }
75}
76
77impl AsyncAuthenticatedTransport for AsyncBasicClient {
78 type Error = TransportError;
79
80 async fn send_authenticated<'transport, 'request, 'policy, 'writer>(
81 &'transport self,
82 request: AuthenticatedRequest<'request, 'policy>,
83 response: &'writer mut ResponseWriter<'_>,
84 ) -> Result<(), Self::Error>
85 where
86 'transport: 'writer,
87 'request: 'writer,
88 'policy: 'writer,
89 {
90 self.send_inner(request, response).await
91 }
92}
93
94impl ResponseStorageSanitizer for AsyncBasicClient {
95 fn sanitize_response_storage(&self, response_storage: &mut [u8]) {
96 sanitize_bytes(response_storage);
97 }
98}
99
100impl BoundTransport for AsyncBasicClient {
101 fn endpoint_identity(&self) -> Result<EndpointIdentity<'_>, EndpointIdentityError> {
102 self.endpoint.identity()
103 }
104}
105
106impl fmt::Debug for AsyncBasicClient {
107 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
108 formatter
109 .debug_struct("AsyncBasicClient")
110 .field("endpoint", &"[redacted]")
111 .field("credential", &"[redacted]")
112 .finish_non_exhaustive()
113 }
114}