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