Skip to main content

cloud_sdk_testkit/
prepared.rs

1//! Redacted records of prepared request policy and shape.
2
3use core::fmt;
4
5use cloud_sdk::Method;
6use cloud_sdk::authentication::AuthenticationScopePolicy;
7use cloud_sdk::operation::{OperationMetadata, PreparedRequest, ProviderService, ResponsePolicy};
8use cloud_sdk::transport::{HeaderSensitivity, RawResponsePolicy};
9
10/// Non-secret record of one prepared request for policy assertions.
11#[derive(Clone, Copy, Eq, PartialEq)]
12pub struct PreparedRequestRecord<'endpoint> {
13    method: Method,
14    target_len: usize,
15    body_len: usize,
16    has_request_content_type: bool,
17    header_count: usize,
18    sensitive_header_count: usize,
19    service: ProviderService<'endpoint>,
20    metadata: OperationMetadata,
21    response_policy: ResponsePolicy,
22    authentication_policy: AuthenticationScopePolicy<'endpoint>,
23    raw_response_policy: RawResponsePolicy<'endpoint>,
24}
25
26impl<'endpoint> PreparedRequestRecord<'endpoint> {
27    /// Captures request shape and complete policy without copying target or body bytes.
28    #[must_use]
29    pub fn capture(prepared: PreparedRequest<'endpoint>) -> Self {
30        let request = prepared.transport_request();
31        Self {
32            method: request.method(),
33            target_len: request.target().len(),
34            body_len: request.body().len(),
35            has_request_content_type: request.headers().get("content-type").is_some(),
36            header_count: request.headers().as_slice().len(),
37            sensitive_header_count: request
38                .headers()
39                .as_slice()
40                .iter()
41                .filter(|header| matches!(header.sensitivity(), HeaderSensitivity::Sensitive))
42                .count(),
43            service: prepared.service(),
44            metadata: prepared.metadata(),
45            response_policy: prepared.response_policy(),
46            authentication_policy: prepared.authentication_policy(),
47            raw_response_policy: prepared.raw_response_policy(),
48        }
49    }
50
51    /// Returns the HTTP method.
52    #[must_use]
53    pub const fn method(self) -> Method {
54        self.method
55    }
56
57    /// Returns the redacted request-target length.
58    #[must_use]
59    pub const fn target_len(self) -> usize {
60        self.target_len
61    }
62
63    /// Returns the redacted request-body length.
64    #[must_use]
65    pub const fn body_len(self) -> usize {
66        self.body_len
67    }
68
69    /// Reports whether a request content type is configured.
70    #[must_use]
71    pub const fn has_request_content_type(self) -> bool {
72        self.has_request_content_type
73    }
74
75    /// Returns the request-header count without exposing values.
76    #[must_use]
77    pub const fn header_count(self) -> usize {
78        self.header_count
79    }
80
81    /// Returns the number of headers marked sensitive.
82    #[must_use]
83    pub const fn sensitive_header_count(self) -> usize {
84        self.sensitive_header_count
85    }
86
87    /// Returns the bound provider service and endpoint.
88    #[must_use]
89    pub const fn service(self) -> ProviderService<'endpoint> {
90        self.service
91    }
92
93    /// Returns complete operation safety and retry metadata.
94    #[must_use]
95    pub const fn metadata(self) -> OperationMetadata {
96        self.metadata
97    }
98
99    /// Returns complete checked-response policy.
100    #[must_use]
101    pub const fn response_policy(self) -> ResponsePolicy {
102        self.response_policy
103    }
104
105    /// Returns the mandatory authentication-scope policy.
106    #[must_use]
107    pub const fn authentication_policy(self) -> AuthenticationScopePolicy<'endpoint> {
108        self.authentication_policy
109    }
110
111    /// Returns the status-class raw response policy.
112    #[must_use]
113    pub const fn raw_response_policy(self) -> RawResponsePolicy<'endpoint> {
114        self.raw_response_policy
115    }
116}
117
118impl fmt::Debug for PreparedRequestRecord<'_> {
119    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
120        formatter
121            .debug_struct("PreparedRequestRecord")
122            .field("method", &self.method)
123            .field("target_len", &self.target_len)
124            .field("target", &"[redacted]")
125            .field("body_len", &self.body_len)
126            .field("body", &"[redacted]")
127            .field("has_request_content_type", &self.has_request_content_type)
128            .field("header_count", &self.header_count)
129            .field("sensitive_header_count", &self.sensitive_header_count)
130            .field("service", &self.service)
131            .field("metadata", &self.metadata)
132            .field("response_policy", &self.response_policy)
133            .field("authentication_policy", &self.authentication_policy)
134            .field("raw_response_policy", &self.raw_response_policy)
135            .finish()
136    }
137}