datadog_api_client/datadogV2/api/
api_static_analysis.rs1use crate::datadog;
5use flate2::{
6 write::{GzEncoder, ZlibEncoder},
7 Compression,
8};
9use log::warn;
10use reqwest::header::{HeaderMap, HeaderValue};
11use serde::{Deserialize, Serialize};
12use std::io::Write;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16#[serde(untagged)]
17pub enum CreateSCAResolveVulnerableSymbolsError {
18 APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
19 UnknownValue(serde_json::Value),
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(untagged)]
25pub enum CreateSCAResultError {
26 APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
27 UnknownValue(serde_json::Value),
28}
29
30#[derive(Debug, Clone)]
32pub struct StaticAnalysisAPI {
33 config: datadog::Configuration,
34 client: reqwest_middleware::ClientWithMiddleware,
35}
36
37impl Default for StaticAnalysisAPI {
38 fn default() -> Self {
39 Self::with_config(datadog::Configuration::default())
40 }
41}
42
43impl StaticAnalysisAPI {
44 pub fn new() -> Self {
45 Self::default()
46 }
47 pub fn with_config(config: datadog::Configuration) -> Self {
48 let mut reqwest_client_builder = reqwest::Client::builder();
49
50 if let Some(proxy_url) = &config.proxy_url {
51 let proxy = reqwest::Proxy::all(proxy_url).expect("Failed to parse proxy URL");
52 reqwest_client_builder = reqwest_client_builder.proxy(proxy);
53 }
54
55 let mut middleware_client_builder =
56 reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap());
57
58 if config.enable_retry {
59 struct RetryableStatus;
60 impl reqwest_retry::RetryableStrategy for RetryableStatus {
61 fn handle(
62 &self,
63 res: &Result<reqwest::Response, reqwest_middleware::Error>,
64 ) -> Option<reqwest_retry::Retryable> {
65 match res {
66 Ok(success) => reqwest_retry::default_on_request_success(success),
67 Err(_) => None,
68 }
69 }
70 }
71 let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder()
72 .build_with_max_retries(config.max_retries);
73
74 let retry_middleware =
75 reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy(
76 backoff_policy,
77 RetryableStatus,
78 );
79
80 middleware_client_builder = middleware_client_builder.with(retry_middleware);
81 }
82
83 let client = middleware_client_builder.build();
84
85 Self { config, client }
86 }
87
88 pub fn with_client_and_config(
89 config: datadog::Configuration,
90 client: reqwest_middleware::ClientWithMiddleware,
91 ) -> Self {
92 Self { config, client }
93 }
94
95 pub async fn create_sca_resolve_vulnerable_symbols(
96 &self,
97 body: crate::datadogV2::model::ResolveVulnerableSymbolsRequest,
98 ) -> Result<
99 crate::datadogV2::model::ResolveVulnerableSymbolsResponse,
100 datadog::Error<CreateSCAResolveVulnerableSymbolsError>,
101 > {
102 match self
103 .create_sca_resolve_vulnerable_symbols_with_http_info(body)
104 .await
105 {
106 Ok(response_content) => {
107 if let Some(e) = response_content.entity {
108 Ok(e)
109 } else {
110 Err(datadog::Error::Serde(serde::de::Error::custom(
111 "response content was None",
112 )))
113 }
114 }
115 Err(err) => Err(err),
116 }
117 }
118
119 pub async fn create_sca_resolve_vulnerable_symbols_with_http_info(
120 &self,
121 body: crate::datadogV2::model::ResolveVulnerableSymbolsRequest,
122 ) -> Result<
123 datadog::ResponseContent<crate::datadogV2::model::ResolveVulnerableSymbolsResponse>,
124 datadog::Error<CreateSCAResolveVulnerableSymbolsError>,
125 > {
126 let local_configuration = &self.config;
127 let operation_id = "v2.create_sca_resolve_vulnerable_symbols";
128 if local_configuration.is_unstable_operation_enabled(operation_id) {
129 warn!("Using unstable operation {operation_id}");
130 } else {
131 let local_error = datadog::UnstableOperationDisabledError {
132 msg: "Operation 'v2.create_sca_resolve_vulnerable_symbols' is not enabled"
133 .to_string(),
134 };
135 return Err(datadog::Error::UnstableOperationDisabledError(local_error));
136 }
137
138 let local_client = &self.client;
139
140 let local_uri_str = format!(
141 "{}/api/v2/static-analysis-sca/vulnerabilities/resolve-vulnerable-symbols",
142 local_configuration.get_operation_host(operation_id)
143 );
144 let mut local_req_builder =
145 local_client.request(reqwest::Method::POST, local_uri_str.as_str());
146
147 let mut headers = HeaderMap::new();
149 headers.insert("Content-Type", HeaderValue::from_static("application/json"));
150 headers.insert("Accept", HeaderValue::from_static("application/json"));
151
152 match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
154 Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
155 Err(e) => {
156 log::warn!("Failed to parse user agent header: {e}, falling back to default");
157 headers.insert(
158 reqwest::header::USER_AGENT,
159 HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
160 )
161 }
162 };
163
164 if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
166 headers.insert(
167 "DD-API-KEY",
168 HeaderValue::from_str(local_key.key.as_str())
169 .expect("failed to parse DD-API-KEY header"),
170 );
171 };
172 if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
173 headers.insert(
174 "DD-APPLICATION-KEY",
175 HeaderValue::from_str(local_key.key.as_str())
176 .expect("failed to parse DD-APPLICATION-KEY header"),
177 );
178 };
179
180 let output = Vec::new();
182 let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter);
183 if body.serialize(&mut ser).is_ok() {
184 if let Some(content_encoding) = headers.get("Content-Encoding") {
185 match content_encoding.to_str().unwrap_or_default() {
186 "gzip" => {
187 let mut enc = GzEncoder::new(Vec::new(), Compression::default());
188 let _ = enc.write_all(ser.into_inner().as_slice());
189 match enc.finish() {
190 Ok(buf) => {
191 local_req_builder = local_req_builder.body(buf);
192 }
193 Err(e) => return Err(datadog::Error::Io(e)),
194 }
195 }
196 "deflate" => {
197 let mut enc = ZlibEncoder::new(Vec::new(), Compression::default());
198 let _ = enc.write_all(ser.into_inner().as_slice());
199 match enc.finish() {
200 Ok(buf) => {
201 local_req_builder = local_req_builder.body(buf);
202 }
203 Err(e) => return Err(datadog::Error::Io(e)),
204 }
205 }
206 "zstd1" => {
207 let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap();
208 let _ = enc.write_all(ser.into_inner().as_slice());
209 match enc.finish() {
210 Ok(buf) => {
211 local_req_builder = local_req_builder.body(buf);
212 }
213 Err(e) => return Err(datadog::Error::Io(e)),
214 }
215 }
216 _ => {
217 local_req_builder = local_req_builder.body(ser.into_inner());
218 }
219 }
220 } else {
221 local_req_builder = local_req_builder.body(ser.into_inner());
222 }
223 }
224
225 local_req_builder = local_req_builder.headers(headers);
226 let local_req = local_req_builder.build()?;
227 log::debug!("request content: {:?}", local_req.body());
228 let local_resp = local_client.execute(local_req).await?;
229
230 let local_status = local_resp.status();
231 let local_content = local_resp.text().await?;
232 log::debug!("response content: {}", local_content);
233
234 if !local_status.is_client_error() && !local_status.is_server_error() {
235 match serde_json::from_str::<crate::datadogV2::model::ResolveVulnerableSymbolsResponse>(
236 &local_content,
237 ) {
238 Ok(e) => {
239 return Ok(datadog::ResponseContent {
240 status: local_status,
241 content: local_content,
242 entity: Some(e),
243 })
244 }
245 Err(e) => return Err(datadog::Error::Serde(e)),
246 };
247 } else {
248 let local_entity: Option<CreateSCAResolveVulnerableSymbolsError> =
249 serde_json::from_str(&local_content).ok();
250 let local_error = datadog::ResponseContent {
251 status: local_status,
252 content: local_content,
253 entity: local_entity,
254 };
255 Err(datadog::Error::ResponseError(local_error))
256 }
257 }
258
259 pub async fn create_sca_result(
260 &self,
261 body: crate::datadogV2::model::ScaRequest,
262 ) -> Result<(), datadog::Error<CreateSCAResultError>> {
263 match self.create_sca_result_with_http_info(body).await {
264 Ok(_) => Ok(()),
265 Err(err) => Err(err),
266 }
267 }
268
269 pub async fn create_sca_result_with_http_info(
270 &self,
271 body: crate::datadogV2::model::ScaRequest,
272 ) -> Result<datadog::ResponseContent<()>, datadog::Error<CreateSCAResultError>> {
273 let local_configuration = &self.config;
274 let operation_id = "v2.create_sca_result";
275 if local_configuration.is_unstable_operation_enabled(operation_id) {
276 warn!("Using unstable operation {operation_id}");
277 } else {
278 let local_error = datadog::UnstableOperationDisabledError {
279 msg: "Operation 'v2.create_sca_result' is not enabled".to_string(),
280 };
281 return Err(datadog::Error::UnstableOperationDisabledError(local_error));
282 }
283
284 let local_client = &self.client;
285
286 let local_uri_str = format!(
287 "{}/api/v2/static-analysis-sca/dependencies",
288 local_configuration.get_operation_host(operation_id)
289 );
290 let mut local_req_builder =
291 local_client.request(reqwest::Method::POST, local_uri_str.as_str());
292
293 let mut headers = HeaderMap::new();
295 headers.insert("Content-Type", HeaderValue::from_static("application/json"));
296 headers.insert("Accept", HeaderValue::from_static("*/*"));
297
298 match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
300 Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
301 Err(e) => {
302 log::warn!("Failed to parse user agent header: {e}, falling back to default");
303 headers.insert(
304 reqwest::header::USER_AGENT,
305 HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
306 )
307 }
308 };
309
310 if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
312 headers.insert(
313 "DD-API-KEY",
314 HeaderValue::from_str(local_key.key.as_str())
315 .expect("failed to parse DD-API-KEY header"),
316 );
317 };
318 if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
319 headers.insert(
320 "DD-APPLICATION-KEY",
321 HeaderValue::from_str(local_key.key.as_str())
322 .expect("failed to parse DD-APPLICATION-KEY header"),
323 );
324 };
325
326 let output = Vec::new();
328 let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter);
329 if body.serialize(&mut ser).is_ok() {
330 if let Some(content_encoding) = headers.get("Content-Encoding") {
331 match content_encoding.to_str().unwrap_or_default() {
332 "gzip" => {
333 let mut enc = GzEncoder::new(Vec::new(), Compression::default());
334 let _ = enc.write_all(ser.into_inner().as_slice());
335 match enc.finish() {
336 Ok(buf) => {
337 local_req_builder = local_req_builder.body(buf);
338 }
339 Err(e) => return Err(datadog::Error::Io(e)),
340 }
341 }
342 "deflate" => {
343 let mut enc = ZlibEncoder::new(Vec::new(), Compression::default());
344 let _ = enc.write_all(ser.into_inner().as_slice());
345 match enc.finish() {
346 Ok(buf) => {
347 local_req_builder = local_req_builder.body(buf);
348 }
349 Err(e) => return Err(datadog::Error::Io(e)),
350 }
351 }
352 "zstd1" => {
353 let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap();
354 let _ = enc.write_all(ser.into_inner().as_slice());
355 match enc.finish() {
356 Ok(buf) => {
357 local_req_builder = local_req_builder.body(buf);
358 }
359 Err(e) => return Err(datadog::Error::Io(e)),
360 }
361 }
362 _ => {
363 local_req_builder = local_req_builder.body(ser.into_inner());
364 }
365 }
366 } else {
367 local_req_builder = local_req_builder.body(ser.into_inner());
368 }
369 }
370
371 local_req_builder = local_req_builder.headers(headers);
372 let local_req = local_req_builder.build()?;
373 log::debug!("request content: {:?}", local_req.body());
374 let local_resp = local_client.execute(local_req).await?;
375
376 let local_status = local_resp.status();
377 let local_content = local_resp.text().await?;
378 log::debug!("response content: {}", local_content);
379
380 if !local_status.is_client_error() && !local_status.is_server_error() {
381 Ok(datadog::ResponseContent {
382 status: local_status,
383 content: local_content,
384 entity: None,
385 })
386 } else {
387 let local_entity: Option<CreateSCAResultError> =
388 serde_json::from_str(&local_content).ok();
389 let local_error = datadog::ResponseContent {
390 status: local_status,
391 content: local_content,
392 entity: local_entity,
393 };
394 Err(datadog::Error::ResponseError(local_error))
395 }
396 }
397}