cloud_sdk/operation/prepared/
construction.rs1use crate::Method;
2use crate::authentication::AuthenticationScopePolicy;
3use crate::operation::{OperationImpact, OperationMetadata, RequestIdPolicy, ResponsePolicy};
4use crate::transport::{RawResponsePolicy, TransportRequest};
5
6use super::{
7 ApprovedReadOnlyPostQuery, BodyReplayability, PreparedRequest, PreparedRequestPolicyError,
8 ProviderService, RequestBodySensitivity,
9};
10
11impl<'request> PreparedRequest<'request> {
12 pub fn validate_construction_policy(
18 method: Method,
19 metadata: OperationMetadata,
20 raw_response_policy: RawResponsePolicy<'_>,
21 ) -> Result<(), PreparedRequestPolicyError> {
22 if matches!(metadata.impact(), OperationImpact::ReadOnly)
23 && !method.permits_direct_read_only()
24 {
25 return Err(PreparedRequestPolicyError::ReadOnlyMethodMismatch);
26 }
27 if metadata.request_id_policy() != RequestIdPolicy::Discard
28 && !raw_response_policy.admits_header("x-request-id")
29 {
30 return Err(PreparedRequestPolicyError::MissingRequestIdHeader);
31 }
32 Ok(())
33 }
34
35 pub fn new(
47 request: TransportRequest<'request>,
48 service: ProviderService<'request>,
49 metadata: OperationMetadata,
50 response_policy: ResponsePolicy,
51 authentication_policy: AuthenticationScopePolicy<'request>,
52 raw_response_policy: RawResponsePolicy<'request>,
53 body_sensitivity: RequestBodySensitivity,
54 ) -> Result<Self, PreparedRequestPolicyError> {
55 Self::new_inner(
56 request,
57 service,
58 metadata,
59 response_policy,
60 authentication_policy,
61 &raw_response_policy,
62 body_sensitivity,
63 None,
64 )
65 }
66
67 #[allow(clippy::too_many_arguments)]
74 pub fn new_read_only_post_query(
75 approval: ApprovedReadOnlyPostQuery,
76 request: TransportRequest<'request>,
77 service: ProviderService<'request>,
78 metadata: OperationMetadata,
79 response_policy: ResponsePolicy,
80 authentication_policy: AuthenticationScopePolicy<'request>,
81 raw_response_policy: RawResponsePolicy<'request>,
82 body_sensitivity: RequestBodySensitivity,
83 ) -> Result<Self, PreparedRequestPolicyError> {
84 let operation_id = approval
85 .validate(
86 request,
87 service,
88 metadata,
89 authentication_policy,
90 body_sensitivity,
91 )
92 .ok_or(PreparedRequestPolicyError::ReadOnlyPostQueryMismatch)?;
93 let mut prepared = Self::new_inner(
94 request,
95 service,
96 metadata,
97 response_policy,
98 authentication_policy,
99 &raw_response_policy,
100 body_sensitivity,
101 Some(approval),
102 )?;
103 prepared.operation_id = Some(operation_id);
104 Ok(prepared)
105 }
106
107 #[allow(clippy::too_many_arguments)]
108 fn new_inner(
109 request: TransportRequest<'request>,
110 service: ProviderService<'request>,
111 metadata: OperationMetadata,
112 response_policy: ResponsePolicy,
113 authentication_policy: AuthenticationScopePolicy<'request>,
114 raw_response_policy: &RawResponsePolicy<'request>,
115 body_sensitivity: RequestBodySensitivity,
116 read_only_post_approval: Option<ApprovedReadOnlyPostQuery>,
117 ) -> Result<Self, PreparedRequestPolicyError> {
118 if read_only_post_approval.is_none() {
119 Self::validate_construction_policy(request.method(), metadata, *raw_response_policy)?;
120 } else if metadata.request_id_policy() != RequestIdPolicy::Discard
121 && !raw_response_policy.admits_header("x-request-id")
122 {
123 return Err(PreparedRequestPolicyError::MissingRequestIdHeader);
124 }
125 Ok(Self {
126 request,
127 service,
128 metadata,
129 response_policy,
130 authentication_policy,
131 raw_response_policy: *raw_response_policy,
132 operation_id: None,
133 body_replayability: if request.body().is_empty() {
134 BodyReplayability::Replayable
135 } else {
136 BodyReplayability::NotReplayable
137 },
138 body_sensitivity,
139 authorization_evidence_required: false,
140 read_only_post_approval,
141 })
142 }
143}