diff --git a/.generator/src/generator/templates/api.j2 b/.generator/src/generator/templates/api.j2 index ab372ab4e..78dcdf14a 100644 --- a/.generator/src/generator/templates/api.j2 +++ b/.generator/src/generator/templates/api.j2 @@ -2,6 +2,7 @@ use reqwest; use serde::{Serialize, Deserialize}; use crate::datadog::*; +use reqwest::header::{HeaderMap, HeaderValue}; {%- for _, _, operation in operations if "x-pagination" in operation %} {%- if loop.first %} use async_stream::try_stream; @@ -13,6 +14,12 @@ use futures_core::stream::Stream; use log::warn; {%- endif %} {%- endfor %} +{%- for _, _, operation in operations if operation.requestBody is defined and not operation|form_parameter %} +{%- if loop.first %} +use std::io::Write; +use flate2::{write::{GzEncoder, ZlibEncoder}, Compression}; +{%- endif %} +{%- endfor %} {%- set structName = name.replace(" ", "")+"API" %} {% for path, method, operation in operations|sort(attribute="2.operationId", case_sensitive=true) %} @@ -83,10 +90,7 @@ pub struct {{ structName }} { impl Default for {{ structName }} { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -103,9 +107,37 @@ impl {{ structName }} { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + let mut middleware_client_builder = + reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); - Self {config, client} + + Self { config, client } } pub fn with_client_and_config(config: configuration::Configuration, client: reqwest_middleware::ClientWithMiddleware) -> Self { @@ -300,18 +332,50 @@ impl {{ structName }} { {%- endif %} {%- endfor %} + // build headers + let mut headers = HeaderMap::new(); + {%- if operation.requestBody %} + {%- set contentTypeHeaders = operation.requestBody.content.keys()|list %} + {%- if contentTypeHeaders %} + {%- if "application/json" in contentTypeHeaders %} + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + {%- else %} + headers.insert("Content-Type", HeaderValue::from_static("{{ contentTypeHeaders[0] }}")); + {%- endif %} + {%- endif %} + {%- endif %} + {%- if operation.responses %} + {%- set acceptHeaders = operation|accept_headers %} + {%- if acceptHeaders %} + {%- if "application/json" in acceptHeaders %} + headers.insert("Accept", HeaderValue::from_static("application/json")); + {%- else %} + headers.insert("Accept", HeaderValue::from_static("{{ acceptHeaders|join(",") }}")); + {%- endif %} + {%- endif %} + {%- endif %} + {% for name, parameter in operation|parameters if parameter.in == "header" %} {%- if not parameter.required %} if let Some(ref local) = {{name|variable_name}} { - local_req_builder = local_req_builder.header("{{name}}", &local.to_string()); - }; + headers.insert("{{name}}", local.to_string().parse().expect("failed to parse {{name}} header")); + } {%- else %} - local_req_builder = local_req_builder.header("{{name}}", &{{name|variable_name}}.to_string()); + headers.insert("{{name}}", {{name|variable_name}}.to_string().parse().expect("failed to parse {{name}} header")); {%- endif %} {%- endfor %} // build user agent - local_req_builder = local_req_builder.header(reqwest::header::USER_AGENT, local_configuration.user_agent.clone()); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth {%- set authMethods = operation.security if "security" in operation else openapi.security %} @@ -321,7 +385,7 @@ impl {{ structName }} { {%- set schema = openapi.components.securitySchemes[name] %} {%- if schema.type == "apiKey" and schema.in != "cookie" %} if let Some(local_key) = local_configuration.auth_keys.get("{{ name }}") { - local_req_builder = local_req_builder.header("{{schema.name}}", &local_key.key); + headers.insert("{{schema.name}}", HeaderValue::from_str(local_key.key.as_str()).expect("failed to parse {{schema.name}} header")); }; {%- endif %} {%- endfor %} @@ -333,11 +397,13 @@ impl {{ structName }} { {%- if formParameter.required %} let mut local_form = reqwest::multipart::Form::new(); local_form = local_form.part("{{formParameter.name}}", reqwest::multipart::Part::bytes({{formParameter.name}}).file_name("{{formParameter.name}}")); + headers.insert("Content-Type", format!("multipart/form-data; boundary={}", local_form.boundary()).parse().unwrap()); local_req_builder = local_req_builder.multipart(local_form); {%- else %} if let Some({{formParameter.name}}) = {{formParameter.name}} { let mut local_form = reqwest::multipart::Form::new(); local_form = local_form.part("{{formParameter.name}}", reqwest::multipart::Part::bytes({{formParameter.name}}).file_name("{{formParameter.name}}")); + headers.insert("Content-Type", format!("multipart/form-data; boundary={}", local_form.boundary()).parse().unwrap()); local_req_builder = local_req_builder.multipart(local_form); }; {%- endif %} @@ -348,10 +414,55 @@ impl {{ structName }} { let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if {{operation.get("x-codegen-request-body-name", "body")|variable_name}}.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new( + Vec::new(), + Compression::default(), + ); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new( + Vec::new(), + Compression::default(), + ); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + }, + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } {%- endif %} + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/.generator/src/generator/templates/configuration.j2 b/.generator/src/generator/templates/configuration.j2 index 0d8408fb1..fa03d72cb 100644 --- a/.generator/src/generator/templates/configuration.j2 +++ b/.generator/src/generator/templates/configuration.j2 @@ -49,6 +49,8 @@ pub struct Configuration { pub server_operation_index: HashMap, pub server_operation_variables: HashMap>, pub proxy_url: Option, + pub enable_retry: bool, + pub max_retries: u32, } impl Configuration { @@ -114,17 +116,16 @@ impl Configuration { pub fn set_proxy_url(&mut self, proxy_url: Option) { self.proxy_url = proxy_url; } + + pub fn set_retry(&mut self, enable_retry: bool, max_retries: u32) { + self.enable_retry = enable_retry; + self.max_retries = max_retries; + } + } impl Default for Configuration { fn default() -> Self { - let user_agent = format!( - "datadog-api-client-rust/{} (rust {}; os {}; arch {})", - option_env!("CARGO_PKG_VERSION").unwrap_or("?"), - option_env!("DD_RUSTC_VERSION").unwrap_or("?"), - env::consts::OS, - env::consts::ARCH, - ); let unstable_operations = HashMap::from([ {%- for version, api in apis.items() %} {%- for operations in api.values() %} @@ -156,7 +157,7 @@ impl Default for Configuration { {%- endif %} Self { - user_agent, + user_agent: DEFAULT_USER_AGENT.clone(), unstable_operations, auth_keys, server_index: 0, @@ -164,6 +165,8 @@ impl Default for Configuration { server_operation_index: HashMap::new(), server_operation_variables: HashMap::new(), proxy_url: None, + enable_retry: false, + max_retries: 3, } } } @@ -192,6 +195,13 @@ ServerConfiguration { {%- endmacro %} lazy_static! { + pub static ref DEFAULT_USER_AGENT: String = format!( + "datadog-api-client-rust/{} (rust {}; os {}; arch {})", + option_env!("CARGO_PKG_VERSION").unwrap_or("?"), + option_env!("DD_RUSTC_VERSION").unwrap_or("?"), + env::consts::OS, + env::consts::ARCH, + ); static ref SERVERS: Vec = { vec![ {%- for server in openapi.servers %} diff --git a/.generator/src/generator/templates/function_mappings.j2 b/.generator/src/generator/templates/function_mappings.j2 index c1c6dd78e..622fa651f 100644 --- a/.generator/src/generator/templates/function_mappings.j2 +++ b/.generator/src/generator/templates/function_mappings.j2 @@ -64,14 +64,14 @@ fn test_{{version}}_{{ operation['operationId'] | snake_case }}(world: &mut Data {%- set schema = parameter[1] | parameter_schema %} {%- if parameter[1].required %} {%- if schema | is_primitive and schema.get("format") == "binary" -%} - let {{ parameter[0] | variable_name }} = _parameters.get("{{ parameter[0] }}").unwrap().as_str().unwrap().as_bytes().to_vec(); + let {{ parameter[0] | variable_name }} = std::fs::read(format!("tests/scenarios/features/v{}/{}", world.api_version, _parameters.get("{{ parameter[0] }}").unwrap().as_str().unwrap())).unwrap(); {%- else -%} let {{ parameter[0] | variable_name }} = serde_json::from_value(_parameters.get("{{ parameter[0] }}").unwrap().clone()).unwrap(); {%- endif -%} {%- else %} let {{ parameter[0] | variable_name }} = _parameters.get("{{ parameter[0] }}").and_then(|param| {%- if schema | is_primitive and schema.get("format") == "binary" -%} - Some(param.as_str().unwrap().as_bytes().to_vec()) + std::fs::read(format!("tests/scenarios/features/v{}/{}", world.api_version, param.as_str().unwrap())).ok() {%- else -%} Some(serde_json::from_value(param.clone()).unwrap()) {%- endif -%} @@ -113,14 +113,14 @@ fn test_{{version}}_{{ operation['operationId'] | snake_case }}_with_pagination( {%- set schema = parameter[1] | parameter_schema %} {%- if parameter[1].required %} {%- if schema | is_primitive and schema.get("format") == "binary" -%} - let {{ parameter[0] | variable_name }} = _parameters.get("{{ parameter[0] }}").unwrap().as_str().unwrap().as_bytes().to_vec(); + let {{ parameter[0] | variable_name }} = std::fs::read(_parameters.get("{{ parameter[0] }}").unwrap().as_str().unwrap()).unwrap(); {%- else -%} let {{ parameter[0] | variable_name }} = serde_json::from_value(_parameters.get("{{ parameter[0] }}").unwrap().clone()).unwrap(); {%- endif -%} {%- else %} let {{ parameter[0] | variable_name }} = _parameters.get("{{ parameter[0] }}").and_then(|param| {%- if schema | is_primitive and schema.get("format") == "binary" -%} - Some(param.as_str().unwrap().as_bytes().to_vec()) + std::fs::read(param.as_str().unwrap()).ok() {%- else -%} Some(serde_json::from_value(param.clone()).unwrap()) {%- endif -%} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e623b9d94..476c89460 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,8 +8,8 @@ on: pull_request: branches: - master - # schedule: - # - cron: "0 1 * * *" + schedule: + - cron: "0 6 * * *" concurrency: group: unit-${{ github.head_ref }} @@ -25,11 +25,14 @@ jobs: github.event_name == 'schedule' steps: - name: Get GitHub App token + if: github.event_name == 'pull_request' id: get_token - uses: tibdex/github-app-token@v1 + uses: tibdex/github-app-token@v2.1.0 with: app_id: ${{ secrets.PIPELINE_GITHUB_APP_ID }} private_key: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} + installation_retrieval_mode: repository + installation_retrieval_payload: DataDog/datadog-api-spec - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -84,7 +87,7 @@ jobs: toolchain: ${{ matrix.rust-version }} - uses: Swatinem/rust-cache@v2 - name: Test - run: cargo build + run: ./run-tests.sh examples: runs-on: ubuntu-latest diff --git a/.github/workflows/test_integration.yml b/.github/workflows/test_integration.yml new file mode 100644 index 000000000..dfa121a4b --- /dev/null +++ b/.github/workflows/test_integration.yml @@ -0,0 +1,92 @@ +name: Run Integration Tests + +on: + pull_request: + branches: + - master + types: + - opened + - reopened + - ready_for_review + - synchronize + - labeled + - unlabeled + schedule: + - cron: "0 5 * * *" + +concurrency: + group: integration-${{ github.head_ref }} + cancel-in-progress: true + +jobs: + integration_tests: + runs-on: ubuntu-latest + if: > + (github.event_name == 'pull_request' && + github.event.pull_request.draft == false && + !contains(github.event.pull_request.labels.*.name, 'ci/skip') && + !contains(github.event.pull_request.head.ref, 'datadog-api-spec/test/') && + contains(github.event.pull_request.labels.*.name, 'ci/integrations')) || + github.event_name == 'schedule' + services: + datadog-agent: + image: gcr.io/datadoghq/agent:latest + ports: + - 8126:8126 + env: + DD_API_KEY: ${{ secrets.DD_API_KEY }} + DD_HOSTNAME: "none" + DD_INSIDE_CI: "true" + steps: + - name: Get GitHub App token + if: github.event_name == 'pull_request' + id: get_token + uses: tibdex/github-app-token@v2.1.0 + with: + app_id: ${{ secrets.PIPELINE_GITHUB_APP_ID }} + private_key: ${{ secrets.PIPELINE_GITHUB_APP_PRIVATE_KEY }} + installation_retrieval_mode: repository + installation_retrieval_payload: DataDog/datadog-api-spec + - name: Checkout code + uses: actions/checkout@v3 + - name: Post pending status check + if: github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') + uses: DataDog/github-actions/post-status-check@v2 + with: + github-token: ${{ steps.get_token.outputs.token }} + repo: datadog-api-spec + status: pending + context: integration + - name: Install Rust + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: "stable" + - uses: Swatinem/rust-cache@v2 + - name: Run integration tests + shell: bash + run: ./run-tests.sh + env: + CI: "true" + DD_AGENT_HOST: localhost + DD_ENV: prod + DD_SERVICE: datadog-api-client-rust + DD_TAGS: "team:integrations-tools-and-libraries" + DD_TEST_CLIENT_API_KEY: ${{ secrets.DD_CLIENT_API_KEY }} + DD_TEST_CLIENT_APP_KEY: ${{ secrets.DD_CLIENT_APP_KEY }} + RECORD: "none" + - name: Post failure status check + if: failure() && github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/') + uses: DataDog/github-actions/post-status-check@v2 + with: + github-token: ${{ steps.get_token.outputs.token }} + repo: datadog-api-spec + status: failure + context: integration + - name: Post success status check + if: "!failure() && github.event_name == 'pull_request' && contains(github.event.pull_request.head.ref, 'datadog-api-spec/generated/')" + uses: DataDog/github-actions/post-status-check@v2 + with: + github-token: ${{ steps.get_token.outputs.token }} + repo: datadog-api-spec + status: success + context: integration \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 34cce63ef..ec77933a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,15 +31,18 @@ version = "0.0.1" [dependencies] async-stream = "0.3.5" +flate2 = "1.0.28" futures-core = "0.3.30" lazy_static = "1.4.0" log = "0.4.20" reqwest = { version = "0.11.24", features = ["multipart"] } -reqwest-middleware = "0.1.6" +reqwest-middleware = "0.2.5" +reqwest-retry = "0.3.0" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.114" serde_with = "3.6.1" url = "2.5.0" +zstd = "0.13.0" [build-dependencies] rustc_version = "0.4.0" @@ -53,7 +56,7 @@ futures = "0.3.28" futures-util = "0.3.30" minijinja = "1.0.10" regex = "1.9.5" -rvcr = { git = "https://github.com/nkzou/rvcr.git", rev = "b8f84bc0dfacd539fdc6f7446637c6276dcbb57c" } +rvcr = { git = "https://github.com/nkzou/rvcr.git", rev = "cb6911dcd05300a95647ed915b94645679fd80eb" } sha256 = "1.4.0" tokio = { version = "1.10", features = ["macros", "rt-multi-thread", "time"] } urlencoding = "2.1.3" diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 23c18cbf6..cf1b9dc57 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -14,12 +14,14 @@ bytes,https://github.com/tokio-rs/bytes,MIT,"Carl Lerche , Se cfg-if,https://github.com/alexcrichton/cfg-if,MIT OR Apache-2.0,Alex Crichton chrono,https://github.com/chronotope/chrono,MIT OR Apache-2.0,The chrono Authors core-foundation,https://github.com/servo/core-foundation-rs,MIT OR Apache-2.0,The Servo Project Developers +crc32fast,https://github.com/srijs/rust-crc32fast,MIT OR Apache-2.0,"Sam Rijs , Alex Crichton " darling,https://github.com/TedDriggs/darling,MIT,Ted Driggs deranged,https://github.com/jhpratt/deranged,MIT OR Apache-2.0,Jacob Pratt encoding_rs,https://github.com/hsivonen/encoding_rs,(Apache-2.0 OR MIT) AND BSD-3-Clause,Henri Sivonen equivalent,https://github.com/cuviper/equivalent,Apache-2.0 OR MIT,The equivalent Authors errno,https://github.com/lambda-fairy/rust-errno,MIT OR Apache-2.0,Chris Wong fastrand,https://github.com/smol-rs/fastrand,Apache-2.0 OR MIT,Stjepan Glavina +flate2,https://github.com/rust-lang/flate2-rs,MIT OR Apache-2.0,"Alex Crichton , Josh Triplett " fnv,https://github.com/servo/rust-fnv,Apache-2.0 OR MIT,Alex Crichton foreign-types,https://github.com/sfackler/foreign-types,MIT OR Apache-2.0,Steven Fackler futures,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures Authors @@ -31,6 +33,7 @@ futures-macro,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futu futures-sink,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-sink Authors futures-task,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-task Authors futures-util,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-util Authors +getrandom,https://github.com/rust-random/getrandom,MIT OR Apache-2.0,The Rand Project Developers gimli,https://github.com/gimli-rs/gimli,MIT OR Apache-2.0,The gimli Authors h2,https://github.com/hyperium/h2,MIT,"Carl Lerche , Sean McArthur " hashbrown,https://github.com/rust-lang/hashbrown,MIT OR Apache-2.0,Amanieu d'Antras @@ -47,12 +50,14 @@ iana-time-zone-haiku,https://github.com/strawlab/iana-time-zone,MIT OR Apache-2. ident_case,https://github.com/TedDriggs/ident_case,MIT OR Apache-2.0,Ted Driggs indexmap,https://github.com/bluss/indexmap,Apache-2.0 OR MIT,The indexmap Authors indexmap,https://github.com/indexmap-rs/indexmap,Apache-2.0 OR MIT,The indexmap Authors +instant,https://github.com/sebcrozet/instant,BSD-3-Clause,sebcrozet ipnet,https://github.com/krisprice/ipnet,MIT OR Apache-2.0,Kris Price itoa,https://github.com/dtolnay/itoa,MIT OR Apache-2.0,David Tolnay js-sys,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/js-sys,MIT OR Apache-2.0,The wasm-bindgen Developers lazy_static,https://github.com/rust-lang-nursery/lazy-static.rs,MIT OR Apache-2.0,Marvin Löbel libc,https://github.com/rust-lang/libc,MIT OR Apache-2.0,The Rust Project Developers linux-raw-sys,https://github.com/sunfishcode/linux-raw-sys,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Dan Gohman +lock_api,https://github.com/Amanieu/parking_lot,MIT OR Apache-2.0,Amanieu d'Antras log,https://github.com/rust-lang/log,MIT OR Apache-2.0,The Rust Project Developers memchr,https://github.com/BurntSushi/memchr,Unlicense OR MIT,"Andrew Gallant , bluss" mime,https://github.com/hyperium/mime,MIT OR Apache-2.0,Sean McArthur @@ -69,18 +74,25 @@ openssl,https://github.com/sfackler/rust-openssl,Apache-2.0,Steven Fackler openssl-sys,https://github.com/sfackler/rust-openssl,MIT,"Alex Crichton , Steven Fackler " +parking_lot,https://github.com/Amanieu/parking_lot,Apache-2.0 OR MIT,Amanieu d'Antras pin-project-lite,https://github.com/taiki-e/pin-project-lite,Apache-2.0 OR MIT,The pin-project-lite Authors pin-utils,https://github.com/rust-lang-nursery/pin-utils,MIT OR Apache-2.0,Josef Brandl powerfmt,https://github.com/jhpratt/powerfmt,MIT OR Apache-2.0,Jacob Pratt +ppv-lite86,https://github.com/cryptocorrosion/cryptocorrosion,MIT OR Apache-2.0,The CryptoCorrosion Contributors proc-macro2,https://github.com/dtolnay/proc-macro2,MIT OR Apache-2.0,"David Tolnay , Alex Crichton " quote,https://github.com/dtolnay/quote,MIT OR Apache-2.0,David Tolnay +rand,https://github.com/rust-random/rand,MIT OR Apache-2.0,"The Rand Project Developers, The Rust Project Developers" +rand_chacha,https://github.com/rust-random/rand,MIT OR Apache-2.0,"The Rand Project Developers, The Rust Project Developers, The CryptoCorrosion Contributors" +redox_syscall,https://gitlab.redox-os.org/redox-os/syscall,MIT,Jeremy Soller reqwest,https://github.com/seanmonstar/reqwest,MIT OR Apache-2.0,Sean McArthur reqwest-middleware,https://github.com/TrueLayer/reqwest-middleware,MIT OR Apache-2.0,Rodrigo Gryzinski +retry-policies,https://github.com/TrueLayer/retry-policies,MIT OR Apache-2.0,Luca Palmieri rustc-demangle,https://github.com/alexcrichton/rustc-demangle,MIT OR Apache-2.0,Alex Crichton rustix,https://github.com/bytecodealliance/rustix,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,"Dan Gohman , Jakub Konka " rustls-pemfile,https://github.com/rustls/pemfile,Apache-2.0 OR ISC OR MIT,The rustls-pemfile Authors ryu,https://github.com/dtolnay/ryu,Apache-2.0 OR BSL-1.0,David Tolnay schannel,https://github.com/steffengy/schannel-rs,MIT,"Steven Fackler , Steffen Butzer " +scopeguard,https://github.com/bluss/scopeguard,MIT OR Apache-2.0,bluss security-framework,https://github.com/kornelski/rust-security-framework,MIT OR Apache-2.0,"Steven Fackler , Kornel " serde,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " serde_json,https://github.com/serde-rs/json,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " @@ -88,6 +100,7 @@ serde_urlencoded,https://github.com/nox/serde_urlencoded,MIT OR Apache-2.0,Antho serde_with,https://github.com/jonasbb/serde_with,MIT OR Apache-2.0,"Jonas Bushart, Marcin Kaźmierczak" serde_with_macros,https://github.com/jonasbb/serde_with,MIT OR Apache-2.0,Jonas Bushart slab,https://github.com/tokio-rs/slab,MIT,Carl Lerche +smallvec,https://github.com/servo/rust-smallvec,MIT OR Apache-2.0,The Servo Project Developers socket2,https://github.com/rust-lang/socket2,MIT OR Apache-2.0,"Alex Crichton , Thomas de Zeeuw " strsim,https://github.com/dguo/strsim-rs,MIT,Danny Guo syn,https://github.com/dtolnay/syn,MIT OR Apache-2.0,David Tolnay @@ -119,7 +132,9 @@ wasm-bindgen-futures,https://github.com/rustwasm/wasm-bindgen/tree/master/crates wasm-bindgen-macro,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-macro-support,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro-support,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-shared,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/shared,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-timer,https://github.com/tomaka/wasm-timer,MIT,Pierre Krieger web-sys,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/web-sys,MIT OR Apache-2.0,The wasm-bindgen Developers +winapi,https://github.com/retep998/winapi-rs,MIT OR Apache-2.0,Peter Atashian windows-core,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft windows-sys,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft windows-targets,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft @@ -131,3 +146,6 @@ windows_x86_64_gnu,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Mic windows_x86_64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft winreg,https://github.com/gentoo90/winreg-rs,MIT,Igor Shaula +zstd,https://github.com/gyscos/zstd-rs,MIT,Alexandre Bury +zstd-safe,https://github.com/gyscos/zstd-rs,MIT OR Apache-2.0,Alexandre Bury +zstd-sys,https://github.com/gyscos/zstd-rs,MIT OR Apache-2.0,Alexandre Bury diff --git a/generate.sh b/generate.sh index 44df2e0a4..2a9c7dcd7 100755 --- a/generate.sh +++ b/generate.sh @@ -27,4 +27,3 @@ rm -rf src/* pre_commit_wrapper generator pre_commit_wrapper format pre_commit_wrapper lint -pre_commit_wrapper license-check diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 000000000..365f3b1e4 --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,5 @@ +./scripts/license-check.sh +if [ $? -ne 0 ]; then + exit 1 +fi +cargo test --test main -- diff --git a/src/datadog/configuration.rs b/src/datadog/configuration.rs index 56b1f8b6d..eecad6dc2 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -51,6 +51,8 @@ pub struct Configuration { pub server_operation_index: HashMap, pub server_operation_variables: HashMap>, pub proxy_url: Option, + pub enable_retry: bool, + pub max_retries: u32, } impl Configuration { @@ -117,17 +119,15 @@ impl Configuration { pub fn set_proxy_url(&mut self, proxy_url: Option) { self.proxy_url = proxy_url; } + + pub fn set_retry(&mut self, enable_retry: bool, max_retries: u32) { + self.enable_retry = enable_retry; + self.max_retries = max_retries; + } } impl Default for Configuration { fn default() -> Self { - let user_agent = format!( - "datadog-api-client-rust/{} (rust {}; os {}; arch {})", - option_env!("CARGO_PKG_VERSION").unwrap_or("?"), - option_env!("DD_RUSTC_VERSION").unwrap_or("?"), - env::consts::OS, - env::consts::ARCH, - ); let unstable_operations = HashMap::from([ ("v2.create_open_api".to_owned(), false), ("v2.delete_open_api".to_owned(), false), @@ -193,7 +193,7 @@ impl Default for Configuration { ); Self { - user_agent, + user_agent: DEFAULT_USER_AGENT.clone(), unstable_operations, auth_keys, server_index: 0, @@ -201,11 +201,20 @@ impl Default for Configuration { server_operation_index: HashMap::new(), server_operation_variables: HashMap::new(), proxy_url: None, + enable_retry: false, + max_retries: 3, } } } lazy_static! { + pub static ref DEFAULT_USER_AGENT: String = format!( + "datadog-api-client-rust/{} (rust {}; os {}; arch {})", + option_env!("CARGO_PKG_VERSION").unwrap_or("?"), + option_env!("DD_RUSTC_VERSION").unwrap_or("?"), + env::consts::OS, + env::consts::ARCH, + ); static ref SERVERS: Vec = { vec![ ServerConfiguration { diff --git a/src/datadogV1/api/api_authentication.rs b/src/datadogV1/api/api_authentication.rs index 7e0447d58..d74bfe331 100644 --- a/src/datadogV1/api/api_authentication.rs +++ b/src/datadogV1/api/api_authentication.rs @@ -3,6 +3,7 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// ValidateError is a struct for typed errors of method [`AuthenticationAPI::validate`] @@ -22,10 +23,7 @@ pub struct AuthenticationAPI { impl Default for AuthenticationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -41,9 +39,36 @@ impl AuthenticationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -92,17 +117,32 @@ impl AuthenticationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_aws_integration.rs b/src/datadogV1/api/api_aws_integration.rs index 43c91a3c5..f97ca6e1c 100644 --- a/src/datadogV1/api/api_aws_integration.rs +++ b/src/datadogV1/api/api_aws_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListAWSAccountsOptionalParams is a struct for passing parameters to the method [`AWSIntegrationAPI::list_aws_accounts`] #[non_exhaustive] @@ -199,10 +205,7 @@ pub struct AWSIntegrationAPI { impl Default for AWSIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -218,9 +221,36 @@ impl AWSIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -277,27 +307,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -374,27 +462,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -466,27 +612,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -558,27 +762,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -650,27 +912,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -747,27 +1067,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -839,27 +1217,85 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -948,20 +1384,39 @@ impl AWSIntegrationAPI { local_req_builder.query(&[("access_key_id", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1033,20 +1488,39 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1120,20 +1594,39 @@ impl AWSIntegrationAPI { local_req_builder = local_req_builder.query(&[("account_id", &account_id.to_string())]); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1199,20 +1692,39 @@ impl AWSIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1302,27 +1814,85 @@ impl AWSIntegrationAPI { local_req_builder.query(&[("access_key_id", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_aws_logs_integration.rs b/src/datadogV1/api/api_aws_logs_integration.rs index d5a5a2b72..1a339b3e3 100644 --- a/src/datadogV1/api/api_aws_logs_integration.rs +++ b/src/datadogV1/api/api_aws_logs_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CheckAWSLogsLambdaAsyncError is a struct for typed errors of method [`AWSLogsIntegrationAPI::check_aws_logs_lambda_async`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -82,10 +88,7 @@ pub struct AWSLogsIntegrationAPI { impl Default for AWSLogsIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -101,9 +104,36 @@ impl AWSLogsIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -168,27 +198,85 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -281,27 +369,85 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -373,27 +519,85 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -465,27 +669,85 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -559,27 +821,85 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -651,20 +971,39 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -736,20 +1075,39 @@ impl AWSLogsIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_azure_integration.rs b/src/datadogV1/api/api_azure_integration.rs index 8b241a7f7..458899026 100644 --- a/src/datadogV1/api/api_azure_integration.rs +++ b/src/datadogV1/api/api_azure_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateAzureIntegrationError is a struct for typed errors of method [`AzureIntegrationAPI::create_azure_integration`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -63,10 +69,7 @@ pub struct AzureIntegrationAPI { impl Default for AzureIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -82,9 +85,36 @@ impl AzureIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -149,27 +179,85 @@ impl AzureIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -243,27 +331,85 @@ impl AzureIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -332,20 +478,39 @@ impl AzureIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -418,27 +583,85 @@ impl AzureIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -516,27 +739,85 @@ impl AzureIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_dashboard_lists.rs b/src/datadogV1/api/api_dashboard_lists.rs index 796cf451d..03c565de0 100644 --- a/src/datadogV1/api/api_dashboard_lists.rs +++ b/src/datadogV1/api/api_dashboard_lists.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateDashboardListError is a struct for typed errors of method [`DashboardListsAPI::create_dashboard_list`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -63,10 +69,7 @@ pub struct DashboardListsAPI { impl Default for DashboardListsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -82,9 +85,36 @@ impl DashboardListsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -134,27 +164,85 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -225,20 +313,39 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -308,20 +415,39 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -389,20 +515,39 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -479,27 +624,85 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_dashboards.rs b/src/datadogV1/api/api_dashboards.rs index 8eb3379b6..2d69f96f1 100644 --- a/src/datadogV1/api/api_dashboards.rs +++ b/src/datadogV1/api/api_dashboards.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetPublicDashboardInvitationsOptionalParams is a struct for passing parameters to the method [`DashboardsAPI::get_public_dashboard_invitations`] #[non_exhaustive] @@ -224,10 +230,7 @@ pub struct DashboardsAPI { impl Default for DashboardsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -243,9 +246,36 @@ impl DashboardsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -295,27 +325,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -384,27 +472,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -474,20 +620,39 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -547,27 +712,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -635,20 +858,39 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -714,27 +956,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -796,20 +1096,39 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -878,20 +1197,39 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -982,20 +1320,39 @@ impl DashboardsAPI { local_req_builder.query(&[("page_number", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1133,20 +1490,39 @@ impl DashboardsAPI { local_req_builder.query(&[("start", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1205,27 +1581,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1298,27 +1732,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1393,27 +1885,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1488,27 +2038,85 @@ impl DashboardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_downtimes.rs b/src/datadogV1/api/api_downtimes.rs index e29010649..94ee778ad 100644 --- a/src/datadogV1/api/api_downtimes.rs +++ b/src/datadogV1/api/api_downtimes.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListDowntimesOptionalParams is a struct for passing parameters to the method [`DowntimesAPI::list_downtimes`] #[non_exhaustive] @@ -107,10 +113,7 @@ pub struct DowntimesAPI { impl Default for DowntimesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -126,9 +129,36 @@ impl DowntimesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -168,20 +198,39 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -246,27 +295,85 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -335,27 +442,85 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -422,20 +587,39 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -514,20 +698,39 @@ impl DowntimesAPI { local_req_builder.query(&[("with_creator", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -597,20 +800,39 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -680,27 +902,85 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_events.rs b/src/datadogV1/api/api_events.rs index 520d301b9..f8c93be29 100644 --- a/src/datadogV1/api/api_events.rs +++ b/src/datadogV1/api/api_events.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListEventsOptionalParams is a struct for passing parameters to the method [`EventsAPI::list_events`] #[non_exhaustive] @@ -101,10 +107,7 @@ pub struct EventsAPI { impl Default for EventsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -120,9 +123,36 @@ impl EventsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -174,24 +204,78 @@ impl EventsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -265,20 +349,39 @@ impl EventsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -399,20 +502,39 @@ impl EventsAPI { local_req_builder.query(&[("page", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_gcp_integration.rs b/src/datadogV1/api/api_gcp_integration.rs index 5da6355cc..f7edad60c 100644 --- a/src/datadogV1/api/api_gcp_integration.rs +++ b/src/datadogV1/api/api_gcp_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateGCPIntegrationError is a struct for typed errors of method [`GCPIntegrationAPI::create_gcp_integration`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -53,10 +59,7 @@ pub struct GCPIntegrationAPI { impl Default for GCPIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -72,9 +75,36 @@ impl GCPIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -127,27 +157,85 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -221,27 +309,85 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -310,20 +456,39 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -401,27 +566,85 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_hosts.rs b/src/datadogV1/api/api_hosts.rs index 4118de605..61b082d04 100644 --- a/src/datadogV1/api/api_hosts.rs +++ b/src/datadogV1/api/api_hosts.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetHostTotalsOptionalParams is a struct for passing parameters to the method [`HostsAPI::get_host_totals`] #[non_exhaustive] @@ -134,10 +140,7 @@ pub struct HostsAPI { impl Default for HostsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -153,9 +156,36 @@ impl HostsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -213,20 +243,39 @@ impl HostsAPI { local_req_builder.query(&[("from", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -342,20 +391,39 @@ impl HostsAPI { .query(&[("include_hosts_metadata", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -425,27 +493,85 @@ impl HostsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -513,20 +639,39 @@ impl HostsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_ip_ranges.rs b/src/datadogV1/api/api_ip_ranges.rs index 0829c9cbe..9e1ffee23 100644 --- a/src/datadogV1/api/api_ip_ranges.rs +++ b/src/datadogV1/api/api_ip_ranges.rs @@ -3,6 +3,7 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// GetIPRangesError is a struct for typed errors of method [`IPRangesAPI::get_ip_ranges`] @@ -21,10 +22,7 @@ pub struct IPRangesAPI { impl Default for IPRangesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -40,9 +38,36 @@ impl IPRangesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -84,14 +109,25 @@ impl IPRangesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_key_management.rs b/src/datadogV1/api/api_key_management.rs index f439fa9f8..38ea7b414 100644 --- a/src/datadogV1/api/api_key_management.rs +++ b/src/datadogV1/api/api_key_management.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateAPIKeyError is a struct for typed errors of method [`KeyManagementAPI::create_api_key`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -116,10 +122,7 @@ pub struct KeyManagementAPI { impl Default for KeyManagementAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -135,9 +138,36 @@ impl KeyManagementAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -185,27 +215,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -274,27 +362,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -364,20 +510,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -447,20 +612,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -530,20 +714,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -613,20 +816,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -693,20 +915,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -775,20 +1016,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -860,27 +1120,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -952,27 +1270,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_logs.rs b/src/datadogV1/api/api_logs.rs index 214e2b5f1..aa00ee128 100644 --- a/src/datadogV1/api/api_logs.rs +++ b/src/datadogV1/api/api_logs.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// SubmitLogOptionalParams is a struct for passing parameters to the method [`LogsAPI::submit_log`] #[non_exhaustive] @@ -55,10 +61,7 @@ pub struct LogsAPI { impl Default for LogsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -74,9 +77,36 @@ impl LogsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -140,27 +170,85 @@ impl LogsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -276,28 +364,88 @@ impl LogsAPI { local_req_builder.query(&[("ddtags", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + if let Some(ref local) = content_encoding { - local_req_builder = local_req_builder.header("Content-Encoding", &local.to_string()); - }; + headers.insert( + "Content-Encoding", + local + .to_string() + .parse() + .expect("failed to parse Content-Encoding header"), + ); + } // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_logs_indexes.rs b/src/datadogV1/api/api_logs_indexes.rs index 0ca3c7aa6..f13c74220 100644 --- a/src/datadogV1/api/api_logs_indexes.rs +++ b/src/datadogV1/api/api_logs_indexes.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateLogsIndexError is a struct for typed errors of method [`LogsIndexesAPI::create_logs_index`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -71,10 +77,7 @@ pub struct LogsIndexesAPI { impl Default for LogsIndexesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -90,9 +93,36 @@ impl LogsIndexesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -140,27 +170,85 @@ impl LogsIndexesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -227,20 +315,39 @@ impl LogsIndexesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -306,20 +413,39 @@ impl LogsIndexesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -389,20 +515,39 @@ impl LogsIndexesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -482,27 +627,85 @@ impl LogsIndexesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -573,27 +776,85 @@ impl LogsIndexesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_logs_pipelines.rs b/src/datadogV1/api/api_logs_pipelines.rs index a19dc6362..230af2d68 100644 --- a/src/datadogV1/api/api_logs_pipelines.rs +++ b/src/datadogV1/api/api_logs_pipelines.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateLogsPipelineError is a struct for typed errors of method [`LogsPipelinesAPI::create_logs_pipeline`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -82,10 +88,7 @@ pub struct LogsPipelinesAPI { impl Default for LogsPipelinesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -101,9 +104,36 @@ impl LogsPipelinesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -153,27 +183,85 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -234,20 +322,39 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -312,20 +419,39 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -394,20 +520,39 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -478,20 +623,39 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -573,27 +737,85 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -671,27 +893,85 @@ impl LogsPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_metrics.rs b/src/datadogV1/api/api_metrics.rs index 70189c8e4..9240ccc0b 100644 --- a/src/datadogV1/api/api_metrics.rs +++ b/src/datadogV1/api/api_metrics.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListActiveMetricsOptionalParams is a struct for passing parameters to the method [`MetricsAPI::list_active_metrics`] #[non_exhaustive] @@ -153,10 +159,7 @@ pub struct MetricsAPI { impl Default for MetricsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -172,9 +175,36 @@ impl MetricsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -225,20 +255,39 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -323,20 +372,39 @@ impl MetricsAPI { local_req_builder.query(&[("tag_filter", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -409,20 +477,39 @@ impl MetricsAPI { local_req_builder = local_req_builder.query(&[("q", &q.to_string())]); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -500,20 +587,39 @@ impl MetricsAPI { local_req_builder = local_req_builder.query(&[("to", &to.to_string())]); local_req_builder = local_req_builder.query(&[("query", &query.to_string())]); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -592,28 +698,88 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("text/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + if let Some(ref local) = content_encoding { - local_req_builder = local_req_builder.header("Content-Encoding", &local.to_string()); - }; + headers.insert( + "Content-Encoding", + local + .to_string() + .parse() + .expect("failed to parse Content-Encoding header"), + ); + } // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -709,28 +875,88 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("text/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + if let Some(ref local) = content_encoding { - local_req_builder = local_req_builder.header("Content-Encoding", &local.to_string()); - }; + headers.insert( + "Content-Encoding", + local + .to_string() + .parse() + .expect("failed to parse Content-Encoding header"), + ); + } // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -807,27 +1033,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_monitors.rs b/src/datadogV1/api/api_monitors.rs index 38db4eae7..588b73b38 100644 --- a/src/datadogV1/api/api_monitors.rs +++ b/src/datadogV1/api/api_monitors.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// DeleteMonitorOptionalParams is a struct for passing parameters to the method [`MonitorsAPI::delete_monitor`] #[non_exhaustive] @@ -349,10 +355,7 @@ pub struct MonitorsAPI { impl Default for MonitorsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -368,9 +371,36 @@ impl MonitorsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -436,20 +466,39 @@ impl MonitorsAPI { .to_string(), )]); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -875,27 +924,85 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -973,20 +1080,39 @@ impl MonitorsAPI { local_req_builder.query(&[("force", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1068,20 +1194,39 @@ impl MonitorsAPI { local_req_builder.query(&[("with_downtimes", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1222,20 +1367,39 @@ impl MonitorsAPI { local_req_builder.query(&[("page_size", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1327,20 +1491,39 @@ impl MonitorsAPI { local_req_builder.query(&[("sort", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1434,20 +1617,39 @@ impl MonitorsAPI { local_req_builder.query(&[("sort", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1518,27 +1720,85 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1616,27 +1876,85 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1712,27 +2030,85 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_notebooks.rs b/src/datadogV1/api/api_notebooks.rs index bdd23f199..f0ca73cd8 100644 --- a/src/datadogV1/api/api_notebooks.rs +++ b/src/datadogV1/api/api_notebooks.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListNotebooksOptionalParams is a struct for passing parameters to the method [`NotebooksAPI::list_notebooks`] #[non_exhaustive] @@ -148,10 +154,7 @@ pub struct NotebooksAPI { impl Default for NotebooksAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -167,9 +170,36 @@ impl NotebooksAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -219,27 +249,85 @@ impl NotebooksAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -299,20 +387,39 @@ impl NotebooksAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -375,20 +482,39 @@ impl NotebooksAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -547,20 +673,39 @@ impl NotebooksAPI { local_req_builder.query(&[("type", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -633,27 +778,85 @@ impl NotebooksAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_organizations.rs b/src/datadogV1/api/api_organizations.rs index eba3126aa..e08952ca2 100644 --- a/src/datadogV1/api/api_organizations.rs +++ b/src/datadogV1/api/api_organizations.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateChildOrgError is a struct for typed errors of method [`OrganizationsAPI::create_child_org`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -73,10 +79,7 @@ pub struct OrganizationsAPI { impl Default for OrganizationsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -92,9 +95,36 @@ impl OrganizationsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -163,27 +193,85 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -255,20 +343,39 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -337,20 +444,39 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -418,20 +544,39 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -502,27 +647,85 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -606,18 +809,40 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Content-Type", + HeaderValue::from_static("multipart/form-data"), ); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build form parameters @@ -626,8 +851,15 @@ impl OrganizationsAPI { "idp_file", reqwest::multipart::Part::bytes(idp_file).file_name("idp_file"), ); + headers.insert( + "Content-Type", + format!("multipart/form-data; boundary={}", local_form.boundary()) + .parse() + .unwrap(), + ); local_req_builder = local_req_builder.multipart(local_form); + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_pager_duty_integration.rs b/src/datadogV1/api/api_pager_duty_integration.rs index e27fb7484..65bdc25bb 100644 --- a/src/datadogV1/api/api_pager_duty_integration.rs +++ b/src/datadogV1/api/api_pager_duty_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreatePagerDutyIntegrationServiceError is a struct for typed errors of method [`PagerDutyIntegrationAPI::create_pager_duty_integration_service`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -54,10 +60,7 @@ pub struct PagerDutyIntegrationAPI { impl Default for PagerDutyIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -73,9 +76,36 @@ impl PagerDutyIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -131,27 +161,85 @@ impl PagerDutyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -215,20 +303,39 @@ impl PagerDutyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -299,20 +406,39 @@ impl PagerDutyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -378,27 +504,85 @@ impl PagerDutyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_security_monitoring.rs b/src/datadogV1/api/api_security_monitoring.rs index 4689d9500..f85978ba2 100644 --- a/src/datadogV1/api/api_security_monitoring.rs +++ b/src/datadogV1/api/api_security_monitoring.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// AddSecurityMonitoringSignalToIncidentError is a struct for typed errors of method [`SecurityMonitoringAPI::add_security_monitoring_signal_to_incident`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -46,10 +52,7 @@ pub struct SecurityMonitoringAPI { impl Default for SecurityMonitoringAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -65,9 +68,36 @@ impl SecurityMonitoringAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -126,27 +156,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -226,27 +314,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -326,27 +472,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_service_checks.rs b/src/datadogV1/api/api_service_checks.rs index 44451ecd4..ea2aa7dab 100644 --- a/src/datadogV1/api/api_service_checks.rs +++ b/src/datadogV1/api/api_service_checks.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// SubmitServiceCheckError is a struct for typed errors of method [`ServiceChecksAPI::submit_service_check`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -25,10 +31,7 @@ pub struct ServiceChecksAPI { impl Default for ServiceChecksAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -44,9 +47,36 @@ impl ServiceChecksAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -105,24 +135,78 @@ impl ServiceChecksAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_service_level_objective_corrections.rs b/src/datadogV1/api/api_service_level_objective_corrections.rs index 96f7555e8..54925de73 100644 --- a/src/datadogV1/api/api_service_level_objective_corrections.rs +++ b/src/datadogV1/api/api_service_level_objective_corrections.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListSLOCorrectionOptionalParams is a struct for passing parameters to the method [`ServiceLevelObjectiveCorrectionsAPI::list_slo_correction`] #[non_exhaustive] @@ -89,10 +95,7 @@ pub struct ServiceLevelObjectiveCorrectionsAPI { impl Default for ServiceLevelObjectiveCorrectionsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -108,9 +111,36 @@ impl ServiceLevelObjectiveCorrectionsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -161,27 +191,85 @@ impl ServiceLevelObjectiveCorrectionsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -245,20 +333,39 @@ impl ServiceLevelObjectiveCorrectionsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -326,20 +433,39 @@ impl ServiceLevelObjectiveCorrectionsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -459,20 +585,39 @@ impl ServiceLevelObjectiveCorrectionsAPI { local_req_builder.query(&[("limit", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -550,27 +695,85 @@ impl ServiceLevelObjectiveCorrectionsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_service_level_objectives.rs b/src/datadogV1/api/api_service_level_objectives.rs index dbfdf9f99..936cda155 100644 --- a/src/datadogV1/api/api_service_level_objectives.rs +++ b/src/datadogV1/api/api_service_level_objectives.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// DeleteSLOOptionalParams is a struct for passing parameters to the method [`ServiceLevelObjectivesAPI::delete_slo`] #[non_exhaustive] @@ -270,10 +276,7 @@ pub struct ServiceLevelObjectivesAPI { impl Default for ServiceLevelObjectivesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -289,9 +292,36 @@ impl ServiceLevelObjectivesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -346,20 +376,39 @@ impl ServiceLevelObjectivesAPI { local_req_builder = local_req_builder.query(&[("ids", &ids.to_string())]); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -428,27 +477,85 @@ impl ServiceLevelObjectivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -531,20 +638,39 @@ impl ServiceLevelObjectivesAPI { local_req_builder.query(&[("force", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -622,27 +748,85 @@ impl ServiceLevelObjectivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -721,20 +905,39 @@ impl ServiceLevelObjectivesAPI { .query(&[("with_configured_alert_ids", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -804,20 +1007,39 @@ impl ServiceLevelObjectivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -927,20 +1149,39 @@ impl ServiceLevelObjectivesAPI { local_req_builder.query(&[("apply_correction", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1076,20 +1317,39 @@ impl ServiceLevelObjectivesAPI { local_req_builder.query(&[("offset", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1178,20 +1438,39 @@ impl ServiceLevelObjectivesAPI { local_req_builder.query(&[("include_facets", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1261,27 +1540,85 @@ impl ServiceLevelObjectivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_slack_integration.rs b/src/datadogV1/api/api_slack_integration.rs index 88e1dffbc..ed6f77d8a 100644 --- a/src/datadogV1/api/api_slack_integration.rs +++ b/src/datadogV1/api/api_slack_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateSlackIntegrationChannelError is a struct for typed errors of method [`SlackIntegrationAPI::create_slack_integration_channel`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -68,10 +74,7 @@ pub struct SlackIntegrationAPI { impl Default for SlackIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -87,9 +90,36 @@ impl SlackIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -148,27 +178,85 @@ impl SlackIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -250,20 +338,39 @@ impl SlackIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -341,20 +448,39 @@ impl SlackIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -422,20 +548,39 @@ impl SlackIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -512,27 +657,85 @@ impl SlackIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_snapshots.rs b/src/datadogV1/api/api_snapshots.rs index 10c483a57..eba73a3f6 100644 --- a/src/datadogV1/api/api_snapshots.rs +++ b/src/datadogV1/api/api_snapshots.rs @@ -3,6 +3,7 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// GetGraphSnapshotOptionalParams is a struct for passing parameters to the method [`SnapshotsAPI::get_graph_snapshot`] @@ -78,10 +79,7 @@ pub struct SnapshotsAPI { impl Default for SnapshotsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -97,9 +95,36 @@ impl SnapshotsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -191,20 +216,39 @@ impl SnapshotsAPI { local_req_builder.query(&[("width", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_synthetics.rs b/src/datadogV1/api/api_synthetics.rs index 19cb08bb9..a022bfa79 100644 --- a/src/datadogV1/api/api_synthetics.rs +++ b/src/datadogV1/api/api_synthetics.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetAPITestLatestResultsOptionalParams is a struct for passing parameters to the method [`SyntheticsAPI::get_api_test_latest_results`] #[non_exhaustive] @@ -385,10 +391,7 @@ pub struct SyntheticsAPI { impl Default for SyntheticsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -404,9 +407,36 @@ impl SyntheticsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -457,27 +487,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -551,27 +639,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -644,27 +790,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -740,27 +944,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -824,20 +1086,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -894,20 +1175,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -972,27 +1272,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1069,27 +1427,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1161,20 +1577,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1277,20 +1712,39 @@ impl SyntheticsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1370,20 +1824,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1457,20 +1930,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1575,20 +2067,39 @@ impl SyntheticsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1670,20 +2181,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1756,20 +2286,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1842,20 +2391,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1928,20 +2496,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2007,20 +2594,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2088,20 +2694,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2172,20 +2797,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2257,20 +2901,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2388,20 +3051,39 @@ impl SyntheticsAPI { local_req_builder.query(&[("page_number", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2474,27 +3156,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2565,27 +3305,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2657,27 +3455,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2750,27 +3606,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2846,27 +3760,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2944,27 +3916,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3038,27 +4068,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_tags.rs b/src/datadogV1/api/api_tags.rs index 596177fd1..f90619945 100644 --- a/src/datadogV1/api/api_tags.rs +++ b/src/datadogV1/api/api_tags.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateHostTagsOptionalParams is a struct for passing parameters to the method [`TagsAPI::create_host_tags`] #[non_exhaustive] @@ -149,10 +155,7 @@ pub struct TagsAPI { impl Default for TagsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -168,9 +171,36 @@ impl TagsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -236,27 +266,85 @@ impl TagsAPI { local_req_builder.query(&[("source", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -330,20 +418,39 @@ impl TagsAPI { local_req_builder.query(&[("source", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -415,20 +522,39 @@ impl TagsAPI { local_req_builder.query(&[("source", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -502,20 +628,39 @@ impl TagsAPI { local_req_builder.query(&[("source", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -599,27 +744,85 @@ impl TagsAPI { local_req_builder.query(&[("source", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_usage_metering.rs b/src/datadogV1/api/api_usage_metering.rs index 6502bc196..3fb7907bf 100644 --- a/src/datadogV1/api/api_usage_metering.rs +++ b/src/datadogV1/api/api_usage_metering.rs @@ -3,6 +3,7 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// GetDailyCustomReportsOptionalParams is a struct for passing parameters to the method [`UsageMeteringAPI::get_daily_custom_reports`] @@ -1130,10 +1131,7 @@ pub struct UsageMeteringAPI { impl Default for UsageMeteringAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -1149,9 +1147,36 @@ impl UsageMeteringAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -1231,20 +1256,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("sort", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1378,20 +1425,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("include_descendants", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1481,20 +1550,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1582,20 +1673,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1696,20 +1809,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("sort", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1853,20 +1988,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("include_descendants", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1948,20 +2105,42 @@ impl UsageMeteringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2043,20 +2222,42 @@ impl UsageMeteringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2144,20 +2345,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2245,20 +2468,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2340,20 +2585,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("month", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2437,20 +2704,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2532,20 +2821,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2633,20 +2944,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2729,20 +3062,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2827,20 +3182,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2924,20 +3301,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3025,20 +3424,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3126,20 +3547,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3222,20 +3665,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3317,20 +3782,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3426,20 +3913,42 @@ impl UsageMeteringAPI { )]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3529,20 +4038,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3630,20 +4161,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3731,20 +4284,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3834,20 +4409,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3935,20 +4532,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4041,20 +4660,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("type", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4141,20 +4782,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4236,20 +4899,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4329,20 +5014,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4430,20 +5137,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("include_org_details", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4531,20 +5260,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4634,20 +5385,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4737,20 +5510,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4838,20 +5633,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -4959,20 +5776,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("next_record_id", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_users.rs b/src/datadogV1/api/api_users.rs index 25bfbabf5..c23cce093 100644 --- a/src/datadogV1/api/api_users.rs +++ b/src/datadogV1/api/api_users.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateUserError is a struct for typed errors of method [`UsersAPI::create_user`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -65,10 +71,7 @@ pub struct UsersAPI { impl Default for UsersAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -84,9 +87,36 @@ impl UsersAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -140,27 +170,85 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -235,20 +323,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -316,20 +423,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -393,20 +519,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -480,27 +625,85 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV1/api/api_webhooks_integration.rs b/src/datadogV1/api/api_webhooks_integration.rs index fa60c25fd..e88415823 100644 --- a/src/datadogV1/api/api_webhooks_integration.rs +++ b/src/datadogV1/api/api_webhooks_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateWebhooksIntegrationError is a struct for typed errors of method [`WebhooksIntegrationAPI::create_webhooks_integration`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -97,10 +103,7 @@ pub struct WebhooksIntegrationAPI { impl Default for WebhooksIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -116,9 +119,36 @@ impl WebhooksIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -169,27 +199,85 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -266,27 +354,85 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -351,20 +497,39 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -421,20 +586,39 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -503,20 +687,39 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -600,20 +803,39 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -692,27 +914,85 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -792,27 +1072,85 @@ impl WebhooksIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_api_management.rs b/src/datadogV2/api/api_api_management.rs index a1c489a8a..56a217d60 100644 --- a/src/datadogV2/api/api_api_management.rs +++ b/src/datadogV2/api/api_api_management.rs @@ -4,6 +4,7 @@ use crate::datadog::*; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// CreateOpenAPIOptionalParams is a struct for passing parameters to the method [`APIManagementAPI::create_open_api`] @@ -89,10 +90,7 @@ pub struct APIManagementAPI { impl Default for APIManagementAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -108,9 +106,36 @@ impl APIManagementAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -179,18 +204,40 @@ impl APIManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Content-Type", + HeaderValue::from_static("multipart/form-data"), ); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build form parameters @@ -200,9 +247,16 @@ impl APIManagementAPI { "openapi_spec_file", reqwest::multipart::Part::bytes(openapi_spec_file).file_name("openapi_spec_file"), ); + headers.insert( + "Content-Type", + format!("multipart/form-data; boundary={}", local_form.boundary()) + .parse() + .unwrap(), + ); local_req_builder = local_req_builder.multipart(local_form); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -268,20 +322,39 @@ impl APIManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -348,20 +421,39 @@ impl APIManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -442,18 +534,40 @@ impl APIManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Content-Type", + HeaderValue::from_static("multipart/form-data"), ); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build form parameters @@ -463,9 +577,16 @@ impl APIManagementAPI { "openapi_spec_file", reqwest::multipart::Part::bytes(openapi_spec_file).file_name("openapi_spec_file"), ); + headers.insert( + "Content-Type", + format!("multipart/form-data; boundary={}", local_form.boundary()) + .parse() + .unwrap(), + ); local_req_builder = local_req_builder.multipart(local_form); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_apm_retention_filters.rs b/src/datadogV2/api/api_apm_retention_filters.rs index 8050b078e..0989487d7 100644 --- a/src/datadogV2/api/api_apm_retention_filters.rs +++ b/src/datadogV2/api/api_apm_retention_filters.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateApmRetentionFilterError is a struct for typed errors of method [`APMRetentionFiltersAPI::create_apm_retention_filter`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -74,10 +80,7 @@ pub struct APMRetentionFiltersAPI { impl Default for APMRetentionFiltersAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -93,9 +96,36 @@ impl APMRetentionFiltersAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -150,27 +180,85 @@ impl APMRetentionFiltersAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -234,20 +322,39 @@ impl APMRetentionFiltersAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -316,20 +423,39 @@ impl APMRetentionFiltersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -401,20 +527,39 @@ impl APMRetentionFiltersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -477,27 +622,85 @@ impl APMRetentionFiltersAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -570,27 +773,85 @@ impl APMRetentionFiltersAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_audit.rs b/src/datadogV2/api/api_audit.rs index 501575ab4..374a3a03f 100644 --- a/src/datadogV2/api/api_audit.rs +++ b/src/datadogV2/api/api_audit.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListAuditLogsOptionalParams is a struct for passing parameters to the method [`AuditAPI::list_audit_logs`] #[non_exhaustive] @@ -100,10 +106,7 @@ pub struct AuditAPI { impl Default for AuditAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -119,9 +122,36 @@ impl AuditAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -248,20 +278,39 @@ impl AuditAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -386,27 +435,85 @@ impl AuditAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_authn_mappings.rs b/src/datadogV2/api/api_authn_mappings.rs index d9f826465..8deb896f5 100644 --- a/src/datadogV2/api/api_authn_mappings.rs +++ b/src/datadogV2/api/api_authn_mappings.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListAuthNMappingsOptionalParams is a struct for passing parameters to the method [`AuthNMappingsAPI::list_authn_mappings`] #[non_exhaustive] @@ -103,10 +109,7 @@ pub struct AuthNMappingsAPI { impl Default for AuthNMappingsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -122,9 +125,36 @@ impl AuthNMappingsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -174,27 +204,85 @@ impl AuthNMappingsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -258,20 +346,39 @@ impl AuthNMappingsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -339,20 +446,39 @@ impl AuthNMappingsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -446,20 +572,39 @@ impl AuthNMappingsAPI { local_req_builder.query(&[("filter", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -536,27 +681,85 @@ impl AuthNMappingsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_case_management.rs b/src/datadogV2/api/api_case_management.rs index 73556cb05..124edb4b7 100644 --- a/src/datadogV2/api/api_case_management.rs +++ b/src/datadogV2/api/api_case_management.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// SearchCasesOptionalParams is a struct for passing parameters to the method [`CaseManagementAPI::search_cases`] #[non_exhaustive] @@ -213,10 +219,7 @@ pub struct CaseManagementAPI { impl Default for CaseManagementAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -232,9 +235,36 @@ impl CaseManagementAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -285,27 +315,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -374,27 +462,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -460,27 +606,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -546,27 +750,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -625,20 +887,39 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -700,20 +981,39 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -780,20 +1080,39 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -857,20 +1176,39 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -999,20 +1337,39 @@ impl CaseManagementAPI { local_req_builder.query(&[("sort[asc]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1081,27 +1438,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1171,27 +1586,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1260,27 +1733,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1350,27 +1881,85 @@ impl CaseManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_ci_visibility_pipelines.rs b/src/datadogV2/api/api_ci_visibility_pipelines.rs index 3fdebb034..aa9131468 100644 --- a/src/datadogV2/api/api_ci_visibility_pipelines.rs +++ b/src/datadogV2/api/api_ci_visibility_pipelines.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListCIAppPipelineEventsOptionalParams is a struct for passing parameters to the method [`CIVisibilityPipelinesAPI::list_ci_app_pipeline_events`] #[non_exhaustive] @@ -125,10 +131,7 @@ pub struct CIVisibilityPipelinesAPI { impl Default for CIVisibilityPipelinesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -144,9 +147,36 @@ impl CIVisibilityPipelinesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -202,27 +232,85 @@ impl CIVisibilityPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -301,24 +389,78 @@ impl CIVisibilityPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -472,20 +614,39 @@ impl CIVisibilityPipelinesAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -615,27 +776,85 @@ impl CIVisibilityPipelinesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_ci_visibility_tests.rs b/src/datadogV2/api/api_ci_visibility_tests.rs index 7aa73234e..bdbfac9ca 100644 --- a/src/datadogV2/api/api_ci_visibility_tests.rs +++ b/src/datadogV2/api/api_ci_visibility_tests.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListCIAppTestEventsOptionalParams is a struct for passing parameters to the method [`CIVisibilityTestsAPI::list_ci_app_test_events`] #[non_exhaustive] @@ -110,10 +116,7 @@ pub struct CIVisibilityTestsAPI { impl Default for CIVisibilityTestsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -129,9 +132,36 @@ impl CIVisibilityTestsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -184,27 +214,85 @@ impl CIVisibilityTestsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -351,20 +439,39 @@ impl CIVisibilityTestsAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -486,27 +593,85 @@ impl CIVisibilityTestsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_cloud_cost_management.rs b/src/datadogV2/api/api_cloud_cost_management.rs index 4cac0997a..5c0f91065 100644 --- a/src/datadogV2/api/api_cloud_cost_management.rs +++ b/src/datadogV2/api/api_cloud_cost_management.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateCostAWSCURConfigError is a struct for typed errors of method [`CloudCostManagementAPI::create_cost_awscur_config`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -109,10 +115,7 @@ pub struct CloudCostManagementAPI { impl Default for CloudCostManagementAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -128,9 +131,36 @@ impl CloudCostManagementAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -181,27 +211,85 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -275,27 +363,85 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -359,20 +505,39 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -429,20 +594,39 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -505,20 +689,39 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -600,20 +803,39 @@ impl CloudCostManagementAPI { &filter_management_account_id.to_string(), )]); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -683,20 +905,39 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -766,20 +1007,39 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -857,27 +1117,85 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -957,27 +1275,85 @@ impl CloudCostManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_cloud_workload_security.rs b/src/datadogV2/api/api_cloud_workload_security.rs index 481441a65..fc2070aa9 100644 --- a/src/datadogV2/api/api_cloud_workload_security.rs +++ b/src/datadogV2/api/api_cloud_workload_security.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateCSMThreatsAgentRuleError is a struct for typed errors of method [`CloudWorkloadSecurityAPI::create_csm_threats_agent_rule`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -135,10 +141,7 @@ pub struct CloudWorkloadSecurityAPI { impl Default for CloudWorkloadSecurityAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -154,9 +157,36 @@ impl CloudWorkloadSecurityAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -212,27 +242,85 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -310,27 +398,85 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -395,20 +541,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -465,20 +630,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -541,20 +725,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -620,20 +823,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -704,20 +926,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -796,20 +1037,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -882,20 +1142,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -971,20 +1250,39 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1067,27 +1365,85 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1170,27 +1526,85 @@ impl CloudWorkloadSecurityAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_cloudflare_integration.rs b/src/datadogV2/api/api_cloudflare_integration.rs index cf19631da..32570baba 100644 --- a/src/datadogV2/api/api_cloudflare_integration.rs +++ b/src/datadogV2/api/api_cloudflare_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateCloudflareAccountError is a struct for typed errors of method [`CloudflareIntegrationAPI::create_cloudflare_account`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -68,10 +74,7 @@ pub struct CloudflareIntegrationAPI { impl Default for CloudflareIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -87,9 +90,36 @@ impl CloudflareIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -142,27 +172,85 @@ impl CloudflareIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -226,20 +314,39 @@ impl CloudflareIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -305,20 +412,39 @@ impl CloudflareIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -390,20 +516,39 @@ impl CloudflareIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -483,27 +628,85 @@ impl CloudflareIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_confluent_cloud.rs b/src/datadogV2/api/api_confluent_cloud.rs index a2e5ca3d3..5effdc1a7 100644 --- a/src/datadogV2/api/api_confluent_cloud.rs +++ b/src/datadogV2/api/api_confluent_cloud.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateConfluentAccountError is a struct for typed errors of method [`ConfluentCloudAPI::create_confluent_account`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -123,10 +129,7 @@ pub struct ConfluentCloudAPI { impl Default for ConfluentCloudAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -142,9 +145,36 @@ impl ConfluentCloudAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -195,27 +225,85 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -295,27 +383,85 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -379,20 +525,39 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -452,20 +617,39 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -531,20 +715,39 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -623,20 +826,39 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -706,20 +928,39 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -797,20 +1038,39 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -888,27 +1148,85 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -991,27 +1309,85 @@ impl ConfluentCloudAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_container_images.rs b/src/datadogV2/api/api_container_images.rs index e3b92330f..81362314e 100644 --- a/src/datadogV2/api/api_container_images.rs +++ b/src/datadogV2/api/api_container_images.rs @@ -5,6 +5,7 @@ use crate::datadog::*; use async_stream::try_stream; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// ListContainerImagesOptionalParams is a struct for passing parameters to the method [`ContainerImagesAPI::list_container_images`] @@ -71,10 +72,7 @@ pub struct ContainerImagesAPI { impl Default for ContainerImagesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -90,9 +88,36 @@ impl ContainerImagesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -206,20 +231,39 @@ impl ContainerImagesAPI { local_req_builder.query(&[("page[cursor]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_containers.rs b/src/datadogV2/api/api_containers.rs index 88e6699a6..38abaf6b0 100644 --- a/src/datadogV2/api/api_containers.rs +++ b/src/datadogV2/api/api_containers.rs @@ -5,6 +5,7 @@ use crate::datadog::*; use async_stream::try_stream; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// ListContainersOptionalParams is a struct for passing parameters to the method [`ContainersAPI::list_containers`] @@ -71,10 +72,7 @@ pub struct ContainersAPI { impl Default for ContainersAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -90,9 +88,36 @@ impl ContainersAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -204,20 +229,39 @@ impl ContainersAPI { local_req_builder.query(&[("page[cursor]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_dashboard_lists.rs b/src/datadogV2/api/api_dashboard_lists.rs index 96c4615a4..0b083475f 100644 --- a/src/datadogV2/api/api_dashboard_lists.rs +++ b/src/datadogV2/api/api_dashboard_lists.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateDashboardListItemsError is a struct for typed errors of method [`DashboardListsAPI::create_dashboard_list_items`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -56,10 +62,7 @@ pub struct DashboardListsAPI { impl Default for DashboardListsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -75,9 +78,36 @@ impl DashboardListsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -136,27 +166,85 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -236,27 +324,85 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -332,20 +478,39 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -425,27 +590,85 @@ impl DashboardListsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_dora_metrics.rs b/src/datadogV2/api/api_dora_metrics.rs index c51c21c40..3f1754fc3 100644 --- a/src/datadogV2/api/api_dora_metrics.rs +++ b/src/datadogV2/api/api_dora_metrics.rs @@ -2,9 +2,15 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateDORADeploymentError is a struct for typed errors of method [`DORAMetricsAPI::create_dora_deployment`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -34,10 +40,7 @@ pub struct DORAMetricsAPI { impl Default for DORAMetricsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -53,9 +56,36 @@ impl DORAMetricsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -124,24 +154,78 @@ impl DORAMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -228,24 +312,78 @@ impl DORAMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_downtimes.rs b/src/datadogV2/api/api_downtimes.rs index c0b37421e..2de712565 100644 --- a/src/datadogV2/api/api_downtimes.rs +++ b/src/datadogV2/api/api_downtimes.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetDowntimeOptionalParams is a struct for passing parameters to the method [`DowntimesAPI::get_downtime`] #[non_exhaustive] @@ -155,10 +161,7 @@ pub struct DowntimesAPI { impl Default for DowntimesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -174,9 +177,36 @@ impl DowntimesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -216,20 +246,39 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -293,27 +342,85 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -392,20 +499,39 @@ impl DowntimesAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -532,20 +658,39 @@ impl DowntimesAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -677,20 +822,39 @@ impl DowntimesAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -764,27 +928,85 @@ impl DowntimesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_events.rs b/src/datadogV2/api/api_events.rs index 74116a0dc..4dcaa0072 100644 --- a/src/datadogV2/api/api_events.rs +++ b/src/datadogV2/api/api_events.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListEventsOptionalParams is a struct for passing parameters to the method [`EventsAPI::list_events`] #[non_exhaustive] @@ -100,10 +106,7 @@ pub struct EventsAPI { impl Default for EventsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -119,9 +122,36 @@ impl EventsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -242,20 +272,39 @@ impl EventsAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -374,27 +423,85 @@ impl EventsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_fastly_integration.rs b/src/datadogV2/api/api_fastly_integration.rs index dd86b0608..9c41c6c44 100644 --- a/src/datadogV2/api/api_fastly_integration.rs +++ b/src/datadogV2/api/api_fastly_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateFastlyAccountError is a struct for typed errors of method [`FastlyIntegrationAPI::create_fastly_account`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -123,10 +129,7 @@ pub struct FastlyIntegrationAPI { impl Default for FastlyIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -142,9 +145,36 @@ impl FastlyIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -195,27 +225,85 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -293,27 +381,85 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -374,20 +520,39 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -447,20 +612,39 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -525,20 +709,39 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -616,20 +819,39 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -699,20 +921,39 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -785,20 +1026,39 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -876,27 +1136,85 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -977,27 +1295,85 @@ impl FastlyIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_gcp_integration.rs b/src/datadogV2/api/api_gcp_integration.rs index f2cd31e89..387a75472 100644 --- a/src/datadogV2/api/api_gcp_integration.rs +++ b/src/datadogV2/api/api_gcp_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// MakeGCPSTSDelegateOptionalParams is a struct for passing parameters to the method [`GCPIntegrationAPI::make_gcpsts_delegate`] #[non_exhaustive] @@ -91,10 +97,7 @@ pub struct GCPIntegrationAPI { impl Default for GCPIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -110,9 +113,36 @@ impl GCPIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -165,27 +195,85 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -246,20 +334,39 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -322,20 +429,39 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -407,20 +533,39 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -497,27 +642,85 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -597,27 +800,85 @@ impl GCPIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_incident_services.rs b/src/datadogV2/api/api_incident_services.rs index 6c6dc2a3a..3c5f42914 100644 --- a/src/datadogV2/api/api_incident_services.rs +++ b/src/datadogV2/api/api_incident_services.rs @@ -2,9 +2,15 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetIncidentServiceOptionalParams is a struct for passing parameters to the method [`IncidentServicesAPI::get_incident_service`] #[non_exhaustive] @@ -127,10 +133,7 @@ pub struct IncidentServicesAPI { impl Default for IncidentServicesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -146,9 +149,36 @@ impl IncidentServicesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -207,27 +237,85 @@ impl IncidentServicesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -299,20 +387,39 @@ impl IncidentServicesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -401,20 +508,39 @@ impl IncidentServicesAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -517,20 +643,39 @@ impl IncidentServicesAPI { local_req_builder.query(&[("filter", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -616,27 +761,85 @@ impl IncidentServicesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_incident_teams.rs b/src/datadogV2/api/api_incident_teams.rs index dd137d834..7c28f8f80 100644 --- a/src/datadogV2/api/api_incident_teams.rs +++ b/src/datadogV2/api/api_incident_teams.rs @@ -2,9 +2,15 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetIncidentTeamOptionalParams is a struct for passing parameters to the method [`IncidentTeamsAPI::get_incident_team`] #[non_exhaustive] @@ -127,10 +133,7 @@ pub struct IncidentTeamsAPI { impl Default for IncidentTeamsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -146,9 +149,36 @@ impl IncidentTeamsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -206,27 +236,85 @@ impl IncidentTeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -295,20 +383,39 @@ impl IncidentTeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -393,20 +500,39 @@ impl IncidentTeamsAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -508,20 +634,39 @@ impl IncidentTeamsAPI { local_req_builder.query(&[("filter", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -606,27 +751,85 @@ impl IncidentTeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_incidents.rs b/src/datadogV2/api/api_incidents.rs index 0add27780..2f7325498 100644 --- a/src/datadogV2/api/api_incidents.rs +++ b/src/datadogV2/api/api_incidents.rs @@ -3,10 +3,16 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetIncidentOptionalParams is a struct for passing parameters to the method [`IncidentsAPI::get_incident`] #[non_exhaustive] @@ -380,10 +386,7 @@ pub struct IncidentsAPI { impl Default for IncidentsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -399,9 +402,36 @@ impl IncidentsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -459,27 +489,85 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -566,27 +654,85 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -671,27 +817,85 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -760,20 +964,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -842,20 +1065,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -923,20 +1165,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1024,20 +1285,39 @@ impl IncidentsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1125,20 +1405,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1224,20 +1523,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1352,20 +1670,39 @@ impl IncidentsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1451,20 +1788,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1546,20 +1902,39 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1697,20 +2072,39 @@ impl IncidentsAPI { local_req_builder.query(&[("page[offset]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1853,20 +2247,39 @@ impl IncidentsAPI { local_req_builder.query(&[("page[offset]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1968,27 +2381,85 @@ impl IncidentsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2092,27 +2563,85 @@ impl IncidentsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2204,27 +2733,85 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2312,27 +2899,85 @@ impl IncidentsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_ip_allowlist.rs b/src/datadogV2/api/api_ip_allowlist.rs index 099bfce39..2f2ca1c3d 100644 --- a/src/datadogV2/api/api_ip_allowlist.rs +++ b/src/datadogV2/api/api_ip_allowlist.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetIPAllowlistError is a struct for typed errors of method [`IPAllowlistAPI::get_ip_allowlist`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -34,10 +40,7 @@ pub struct IPAllowlistAPI { impl Default for IPAllowlistAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -53,9 +56,36 @@ impl IPAllowlistAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -103,20 +133,39 @@ impl IPAllowlistAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -187,27 +236,85 @@ impl IPAllowlistAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_key_management.rs b/src/datadogV2/api/api_key_management.rs index 36d5ea379..3af0d810f 100644 --- a/src/datadogV2/api/api_key_management.rs +++ b/src/datadogV2/api/api_key_management.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetAPIKeyOptionalParams is a struct for passing parameters to the method [`KeyManagementAPI::get_api_key`] #[non_exhaustive] @@ -405,10 +411,7 @@ pub struct KeyManagementAPI { impl Default for KeyManagementAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -424,9 +427,36 @@ impl KeyManagementAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -474,27 +504,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -568,27 +656,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -646,20 +792,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -712,20 +877,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -782,20 +966,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -868,20 +1071,39 @@ impl KeyManagementAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -964,20 +1186,39 @@ impl KeyManagementAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1055,20 +1296,39 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1197,20 +1457,39 @@ impl KeyManagementAPI { local_req_builder.query(&[("filter[category]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1317,20 +1596,39 @@ impl KeyManagementAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1445,20 +1743,39 @@ impl KeyManagementAPI { local_req_builder.query(&[("include", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1530,27 +1847,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1625,27 +2000,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1725,27 +2158,85 @@ impl KeyManagementAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_logs.rs b/src/datadogV2/api/api_logs.rs index 880c3e75e..dd9179da4 100644 --- a/src/datadogV2/api/api_logs.rs +++ b/src/datadogV2/api/api_logs.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListLogsOptionalParams is a struct for passing parameters to the method [`LogsAPI::list_logs`] #[non_exhaustive] @@ -164,10 +170,7 @@ pub struct LogsAPI { impl Default for LogsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -183,9 +186,36 @@ impl LogsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -235,27 +265,85 @@ impl LogsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -386,27 +474,85 @@ impl LogsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -577,20 +723,39 @@ impl LogsAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -716,28 +881,88 @@ impl LogsAPI { local_req_builder.query(&[("ddtags", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + if let Some(ref local) = content_encoding { - local_req_builder = local_req_builder.header("Content-Encoding", &local.to_string()); - }; + headers.insert( + "Content-Encoding", + local + .to_string() + .parse() + .expect("failed to parse Content-Encoding header"), + ); + } // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_logs_archives.rs b/src/datadogV2/api/api_logs_archives.rs index 353908db5..72a88a94c 100644 --- a/src/datadogV2/api/api_logs_archives.rs +++ b/src/datadogV2/api/api_logs_archives.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// AddReadRoleToArchiveError is a struct for typed errors of method [`LogsArchivesAPI::add_read_role_to_archive`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -118,10 +124,7 @@ pub struct LogsArchivesAPI { impl Default for LogsArchivesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -137,9 +140,36 @@ impl LogsArchivesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -184,27 +214,85 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -266,27 +354,85 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -345,20 +491,39 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -421,20 +586,39 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -503,20 +687,39 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -590,20 +793,39 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -668,20 +890,39 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -745,27 +986,85 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -839,27 +1138,85 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -936,27 +1293,85 @@ impl LogsArchivesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_logs_custom_destinations.rs b/src/datadogV2/api/api_logs_custom_destinations.rs index abf28938d..ab89f4a59 100644 --- a/src/datadogV2/api/api_logs_custom_destinations.rs +++ b/src/datadogV2/api/api_logs_custom_destinations.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateLogsCustomDestinationError is a struct for typed errors of method [`LogsCustomDestinationsAPI::create_logs_custom_destination`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -67,10 +73,7 @@ pub struct LogsCustomDestinationsAPI { impl Default for LogsCustomDestinationsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -86,9 +89,36 @@ impl LogsCustomDestinationsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -144,27 +174,85 @@ impl LogsCustomDestinationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -228,20 +316,39 @@ impl LogsCustomDestinationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -312,20 +419,39 @@ impl LogsCustomDestinationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -397,20 +523,39 @@ impl LogsCustomDestinationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -490,27 +635,85 @@ impl LogsCustomDestinationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_logs_metrics.rs b/src/datadogV2/api/api_logs_metrics.rs index 5ef6d5bbc..aee2dd7ff 100644 --- a/src/datadogV2/api/api_logs_metrics.rs +++ b/src/datadogV2/api/api_logs_metrics.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateLogsMetricError is a struct for typed errors of method [`LogsMetricsAPI::create_logs_metric`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -64,10 +70,7 @@ pub struct LogsMetricsAPI { impl Default for LogsMetricsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -83,9 +86,36 @@ impl LogsMetricsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -137,27 +167,85 @@ impl LogsMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -218,20 +306,39 @@ impl LogsMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -296,20 +403,39 @@ impl LogsMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -378,20 +504,39 @@ impl LogsMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -470,27 +615,85 @@ impl LogsMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_metrics.rs b/src/datadogV2/api/api_metrics.rs index e6325e18a..1c5651a01 100644 --- a/src/datadogV2/api/api_metrics.rs +++ b/src/datadogV2/api/api_metrics.rs @@ -2,9 +2,15 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// EstimateMetricsOutputSeriesOptionalParams is a struct for passing parameters to the method [`MetricsAPI::estimate_metrics_output_series`] #[non_exhaustive] @@ -327,10 +333,7 @@ pub struct MetricsAPI { impl Default for MetricsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -346,9 +349,36 @@ impl MetricsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -416,27 +446,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -524,27 +612,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -627,27 +773,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -713,20 +917,39 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -827,20 +1050,39 @@ impl MetricsAPI { local_req_builder.query(&[("filter[timespan_h]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -928,20 +1170,39 @@ impl MetricsAPI { local_req_builder.query(&[("window[seconds]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1014,20 +1275,39 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1105,20 +1385,39 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1232,20 +1531,39 @@ impl MetricsAPI { local_req_builder.query(&[("window[seconds]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1322,20 +1640,39 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1415,20 +1752,39 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1512,27 +1868,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1616,27 +2030,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1734,28 +2206,88 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + if let Some(ref local) = content_encoding { - local_req_builder = local_req_builder.header("Content-Encoding", &local.to_string()); - }; + headers.insert( + "Content-Encoding", + local + .to_string() + .parse() + .expect("failed to parse Content-Encoding header"), + ); + } // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1843,27 +2375,85 @@ impl MetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_monitors.rs b/src/datadogV2/api/api_monitors.rs index c73dfd44e..dbc9b8ad8 100644 --- a/src/datadogV2/api/api_monitors.rs +++ b/src/datadogV2/api/api_monitors.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateMonitorConfigPolicyError is a struct for typed errors of method [`MonitorsAPI::create_monitor_config_policy`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -64,10 +70,7 @@ pub struct MonitorsAPI { impl Default for MonitorsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -83,9 +86,36 @@ impl MonitorsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -138,27 +168,85 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -222,20 +310,39 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -306,20 +413,39 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -391,20 +517,39 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -484,27 +629,85 @@ impl MonitorsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_okta_integration.rs b/src/datadogV2/api/api_okta_integration.rs index 0e64b802b..486d1a1ad 100644 --- a/src/datadogV2/api/api_okta_integration.rs +++ b/src/datadogV2/api/api_okta_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateOktaAccountError is a struct for typed errors of method [`OktaIntegrationAPI::create_okta_account`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -68,10 +74,7 @@ pub struct OktaIntegrationAPI { impl Default for OktaIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -87,9 +90,36 @@ impl OktaIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -139,27 +169,85 @@ impl OktaIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -220,20 +308,39 @@ impl OktaIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -298,20 +405,39 @@ impl OktaIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -380,20 +506,39 @@ impl OktaIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -470,27 +615,85 @@ impl OktaIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_opsgenie_integration.rs b/src/datadogV2/api/api_opsgenie_integration.rs index f54c525ef..6c83ed354 100644 --- a/src/datadogV2/api/api_opsgenie_integration.rs +++ b/src/datadogV2/api/api_opsgenie_integration.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateOpsgenieServiceError is a struct for typed errors of method [`OpsgenieIntegrationAPI::create_opsgenie_service`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -68,10 +74,7 @@ pub struct OpsgenieIntegrationAPI { impl Default for OpsgenieIntegrationAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -87,9 +90,36 @@ impl OpsgenieIntegrationAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -140,27 +170,85 @@ impl OpsgenieIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -224,20 +312,39 @@ impl OpsgenieIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -306,20 +413,39 @@ impl OpsgenieIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -389,20 +515,39 @@ impl OpsgenieIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -480,27 +625,85 @@ impl OpsgenieIntegrationAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_organizations.rs b/src/datadogV2/api/api_organizations.rs index 232656cc3..463d8a87a 100644 --- a/src/datadogV2/api/api_organizations.rs +++ b/src/datadogV2/api/api_organizations.rs @@ -3,6 +3,7 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// UploadIdPMetadataOptionalParams is a struct for passing parameters to the method [`OrganizationsAPI::upload_idp_metadata`] @@ -39,10 +40,7 @@ pub struct OrganizationsAPI { impl Default for OrganizationsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -58,9 +56,36 @@ impl OrganizationsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -106,18 +131,40 @@ impl OrganizationsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Content-Type", + HeaderValue::from_static("multipart/form-data"), ); + headers.insert("Accept", HeaderValue::from_static("*/*")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build form parameters @@ -127,9 +174,16 @@ impl OrganizationsAPI { "idp_file", reqwest::multipart::Part::bytes(idp_file).file_name("idp_file"), ); + headers.insert( + "Content-Type", + format!("multipart/form-data; boundary={}", local_form.boundary()) + .parse() + .unwrap(), + ); local_req_builder = local_req_builder.multipart(local_form); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_powerpack.rs b/src/datadogV2/api/api_powerpack.rs index aa4544a35..787c40243 100644 --- a/src/datadogV2/api/api_powerpack.rs +++ b/src/datadogV2/api/api_powerpack.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListPowerpacksOptionalParams is a struct for passing parameters to the method [`PowerpackAPI::list_powerpacks`] #[non_exhaustive] @@ -83,10 +89,7 @@ pub struct PowerpackAPI { impl Default for PowerpackAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -102,9 +105,36 @@ impl PowerpackAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -154,27 +184,85 @@ impl PowerpackAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -234,20 +322,39 @@ impl PowerpackAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -310,20 +417,39 @@ impl PowerpackAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -439,20 +565,39 @@ impl PowerpackAPI { local_req_builder.query(&[("page[offset]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -529,27 +674,85 @@ impl PowerpackAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_processes.rs b/src/datadogV2/api/api_processes.rs index cb5cf6ebf..f22326f70 100644 --- a/src/datadogV2/api/api_processes.rs +++ b/src/datadogV2/api/api_processes.rs @@ -5,6 +5,7 @@ use crate::datadog::*; use async_stream::try_stream; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// ListProcessesOptionalParams is a struct for passing parameters to the method [`ProcessesAPI::list_processes`] @@ -86,10 +87,7 @@ pub struct ProcessesAPI { impl Default for ProcessesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -105,9 +103,36 @@ impl ProcessesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -223,20 +248,39 @@ impl ProcessesAPI { local_req_builder.query(&[("page[cursor]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_restriction_policies.rs b/src/datadogV2/api/api_restriction_policies.rs index c3d59840e..340635907 100644 --- a/src/datadogV2/api/api_restriction_policies.rs +++ b/src/datadogV2/api/api_restriction_policies.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// DeleteRestrictionPolicyError is a struct for typed errors of method [`RestrictionPoliciesAPI::delete_restriction_policy`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -43,10 +49,7 @@ pub struct RestrictionPoliciesAPI { impl Default for RestrictionPoliciesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -62,9 +65,36 @@ impl RestrictionPoliciesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -107,20 +137,39 @@ impl RestrictionPoliciesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -189,20 +238,39 @@ impl RestrictionPoliciesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -316,27 +384,85 @@ impl RestrictionPoliciesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_roles.rs b/src/datadogV2/api/api_roles.rs index 0047a2144..71aa4d15a 100644 --- a/src/datadogV2/api/api_roles.rs +++ b/src/datadogV2/api/api_roles.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListRoleUsersOptionalParams is a struct for passing parameters to the method [`RolesAPI::list_role_users`] #[non_exhaustive] @@ -239,10 +245,7 @@ pub struct RolesAPI { impl Default for RolesAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -258,9 +261,36 @@ impl RolesAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -316,27 +346,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -408,27 +496,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -497,27 +643,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -583,27 +787,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -660,20 +922,39 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -734,20 +1015,39 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -813,20 +1113,39 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -898,20 +1217,39 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1006,20 +1344,39 @@ impl RolesAPI { local_req_builder.query(&[("filter", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1114,20 +1471,39 @@ impl RolesAPI { local_req_builder.query(&[("filter[id]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1202,27 +1578,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1299,27 +1733,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1389,27 +1881,85 @@ impl RolesAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_rum.rs b/src/datadogV2/api/api_rum.rs index 39dd0157e..7e8216925 100644 --- a/src/datadogV2/api/api_rum.rs +++ b/src/datadogV2/api/api_rum.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListRUMEventsOptionalParams is a struct for passing parameters to the method [`RUMAPI::list_rum_events`] #[non_exhaustive] @@ -143,10 +149,7 @@ pub struct RUMAPI { impl Default for RUMAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -162,9 +165,36 @@ impl RUMAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -217,27 +247,85 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -309,27 +397,85 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -390,20 +536,39 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -469,20 +634,39 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -552,20 +736,39 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -713,20 +916,39 @@ impl RUMAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -843,27 +1065,85 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -937,27 +1217,85 @@ impl RUMAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_security_monitoring.rs b/src/datadogV2/api/api_security_monitoring.rs index 02da042ea..754e7a196 100644 --- a/src/datadogV2/api/api_security_monitoring.rs +++ b/src/datadogV2/api/api_security_monitoring.rs @@ -3,10 +3,16 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetFindingOptionalParams is a struct for passing parameters to the method [`SecurityMonitoringAPI::get_finding`] #[non_exhaustive] @@ -476,10 +482,7 @@ pub struct SecurityMonitoringAPI { impl Default for SecurityMonitoringAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -495,9 +498,36 @@ impl SecurityMonitoringAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -554,27 +584,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -651,27 +739,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -748,27 +894,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -833,20 +1037,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -903,20 +1126,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -973,20 +1215,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1059,27 +1320,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1160,27 +1479,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1261,27 +1638,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1370,20 +1805,39 @@ impl SecurityMonitoringAPI { local_req_builder.query(&[("snapshot_timestamp", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1464,20 +1918,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1555,20 +2028,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1646,20 +2138,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1737,20 +2248,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1989,20 +2519,39 @@ impl SecurityMonitoringAPI { local_req_builder.query(&[("filter[status]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2071,20 +2620,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2174,20 +2742,39 @@ impl SecurityMonitoringAPI { local_req_builder.query(&[("page[number]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2339,20 +2926,39 @@ impl SecurityMonitoringAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2428,20 +3034,39 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2521,27 +3146,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2668,27 +3351,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2769,27 +3510,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2873,27 +3672,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -2973,27 +3830,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -3057,27 +3972,85 @@ impl SecurityMonitoringAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_sensitive_data_scanner.rs b/src/datadogV2/api/api_sensitive_data_scanner.rs index 141a3249e..6b065b2ac 100644 --- a/src/datadogV2/api/api_sensitive_data_scanner.rs +++ b/src/datadogV2/api/api_sensitive_data_scanner.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateScanningGroupError is a struct for typed errors of method [`SensitiveDataScannerAPI::create_scanning_group`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -107,10 +113,7 @@ pub struct SensitiveDataScannerAPI { impl Default for SensitiveDataScannerAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -126,9 +129,36 @@ impl SensitiveDataScannerAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -189,27 +219,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -292,27 +380,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -393,27 +539,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -494,27 +698,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -587,20 +849,39 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -673,20 +954,39 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -761,27 +1061,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -868,27 +1226,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -975,27 +1391,85 @@ impl SensitiveDataScannerAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_service_accounts.rs b/src/datadogV2/api/api_service_accounts.rs index 6d9bdd820..c9e511a93 100644 --- a/src/datadogV2/api/api_service_accounts.rs +++ b/src/datadogV2/api/api_service_accounts.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListServiceAccountApplicationKeysOptionalParams is a struct for passing parameters to the method [`ServiceAccountsAPI::list_service_account_application_keys`] #[non_exhaustive] @@ -130,10 +136,7 @@ pub struct ServiceAccountsAPI { impl Default for ServiceAccountsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -149,9 +152,36 @@ impl ServiceAccountsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -201,27 +231,85 @@ impl ServiceAccountsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -299,27 +387,85 @@ impl ServiceAccountsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -386,20 +532,39 @@ impl ServiceAccountsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -473,20 +638,39 @@ impl ServiceAccountsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -599,20 +783,39 @@ impl ServiceAccountsAPI { .query(&[("filter[created_at][end]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -699,27 +902,85 @@ impl ServiceAccountsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_service_definition.rs b/src/datadogV2/api/api_service_definition.rs index 04ce1de09..569881967 100644 --- a/src/datadogV2/api/api_service_definition.rs +++ b/src/datadogV2/api/api_service_definition.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetServiceDefinitionOptionalParams is a struct for passing parameters to the method [`ServiceDefinitionAPI::get_service_definition`] #[non_exhaustive] @@ -110,10 +116,7 @@ pub struct ServiceDefinitionAPI { impl Default for ServiceDefinitionAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -129,9 +132,36 @@ impl ServiceDefinitionAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -187,27 +217,85 @@ impl ServiceDefinitionAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -271,20 +359,39 @@ impl ServiceDefinitionAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -365,20 +472,39 @@ impl ServiceDefinitionAPI { local_req_builder.query(&[("schema_version", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -507,20 +633,39 @@ impl ServiceDefinitionAPI { local_req_builder.query(&[("schema_version", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_service_scorecards.rs b/src/datadogV2/api/api_service_scorecards.rs index 144d090ec..0fde6dced 100644 --- a/src/datadogV2/api/api_service_scorecards.rs +++ b/src/datadogV2/api/api_service_scorecards.rs @@ -3,10 +3,16 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListScorecardOutcomesOptionalParams is a struct for passing parameters to the method [`ServiceScorecardsAPI::list_scorecard_outcomes`] #[non_exhaustive] @@ -225,10 +231,7 @@ pub struct ServiceScorecardsAPI { impl Default for ServiceScorecardsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -244,9 +247,36 @@ impl ServiceScorecardsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -310,27 +340,85 @@ impl ServiceScorecardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -409,27 +497,85 @@ impl ServiceScorecardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -498,20 +644,39 @@ impl ServiceScorecardsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -676,20 +841,39 @@ impl ServiceScorecardsAPI { local_req_builder.query(&[("filter[rule][name]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -858,20 +1042,39 @@ impl ServiceScorecardsAPI { local_req_builder.query(&[("fields[scorecard]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_spans.rs b/src/datadogV2/api/api_spans.rs index 044497197..f19d421c1 100644 --- a/src/datadogV2/api/api_spans.rs +++ b/src/datadogV2/api/api_spans.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListSpansGetOptionalParams is a struct for passing parameters to the method [`SpansAPI::list_spans_get`] #[non_exhaustive] @@ -98,10 +104,7 @@ pub struct SpansAPI { impl Default for SpansAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -117,9 +120,36 @@ impl SpansAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -171,27 +201,85 @@ impl SpansAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -314,27 +402,85 @@ impl SpansAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -480,20 +626,39 @@ impl SpansAPI { local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_spans_metrics.rs b/src/datadogV2/api/api_spans_metrics.rs index 38053ec6f..d502f3457 100644 --- a/src/datadogV2/api/api_spans_metrics.rs +++ b/src/datadogV2/api/api_spans_metrics.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// CreateSpansMetricError is a struct for typed errors of method [`SpansMetricsAPI::create_spans_metric`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -64,10 +70,7 @@ pub struct SpansMetricsAPI { impl Default for SpansMetricsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -83,9 +86,36 @@ impl SpansMetricsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -137,27 +167,85 @@ impl SpansMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -218,20 +306,39 @@ impl SpansMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -296,20 +403,39 @@ impl SpansMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -378,20 +504,39 @@ impl SpansMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -470,27 +615,85 @@ impl SpansMetricsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_synthetics.rs b/src/datadogV2/api/api_synthetics.rs index 4915941b5..54732e3e9 100644 --- a/src/datadogV2/api/api_synthetics.rs +++ b/src/datadogV2/api/api_synthetics.rs @@ -2,8 +2,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetOnDemandConcurrencyCapError is a struct for typed errors of method [`SyntheticsAPI::get_on_demand_concurrency_cap`] #[derive(Debug, Clone, Serialize, Deserialize)] @@ -29,10 +35,7 @@ pub struct SyntheticsAPI { impl Default for SyntheticsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -48,9 +51,36 @@ impl SyntheticsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -101,20 +131,39 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -191,27 +240,85 @@ impl SyntheticsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_teams.rs b/src/datadogV2/api/api_teams.rs index e5ce1c84f..be15ced86 100644 --- a/src/datadogV2/api/api_teams.rs +++ b/src/datadogV2/api/api_teams.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// GetTeamMembershipsOptionalParams is a struct for passing parameters to the method [`TeamsAPI::get_team_memberships`] #[non_exhaustive] @@ -282,10 +288,7 @@ pub struct TeamsAPI { impl Default for TeamsAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -301,9 +304,36 @@ impl TeamsAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -353,27 +383,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -444,27 +532,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -540,27 +686,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -617,20 +821,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -686,20 +909,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -759,20 +1001,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -834,20 +1095,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -917,20 +1197,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -998,20 +1297,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1143,20 +1461,39 @@ impl TeamsAPI { local_req_builder.query(&[("filter[keyword]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1233,20 +1570,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1318,20 +1674,39 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1485,20 +1860,39 @@ impl TeamsAPI { )]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1569,27 +1963,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1666,27 +2118,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1765,27 +2275,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1867,27 +2435,85 @@ impl TeamsAPI { let mut local_req_builder = local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_usage_metering.rs b/src/datadogV2/api/api_usage_metering.rs index fb71a3592..95f8966a0 100644 --- a/src/datadogV2/api/api_usage_metering.rs +++ b/src/datadogV2/api/api_usage_metering.rs @@ -4,6 +4,7 @@ use crate::datadog::*; use log::warn; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; /// GetCostByOrgOptionalParams is a struct for passing parameters to the method [`UsageMeteringAPI::get_cost_by_org`] @@ -368,10 +369,7 @@ pub struct UsageMeteringAPI { impl Default for UsageMeteringAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -387,9 +385,36 @@ impl UsageMeteringAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -448,20 +473,42 @@ impl UsageMeteringAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -552,20 +599,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_month", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -668,20 +737,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_date", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -773,20 +864,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_month", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -910,20 +1023,42 @@ impl UsageMeteringAPI { .query(&[("page[next_record_id]", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1071,20 +1206,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("include_descendants", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1167,20 +1324,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("view", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1270,20 +1449,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1374,20 +1575,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -1478,20 +1701,42 @@ impl UsageMeteringAPI { local_req_builder.query(&[("end_hr", &local_query_param.to_string())]); }; - // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), + // build headers + let mut headers = HeaderMap::new(); + headers.insert( + "Accept", + HeaderValue::from_static("application/json;datetime-format=rfc3339"), ); + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/src/datadogV2/api/api_users.rs b/src/datadogV2/api/api_users.rs index 01de7ed7c..024c6c66f 100644 --- a/src/datadogV2/api/api_users.rs +++ b/src/datadogV2/api/api_users.rs @@ -3,9 +3,15 @@ // Copyright 2019-Present Datadog, Inc. use crate::datadog::*; use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; use futures_core::stream::Stream; use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; /// ListUsersOptionalParams is a struct for passing parameters to the method [`UsersAPI::list_users`] #[non_exhaustive] @@ -168,10 +174,7 @@ pub struct UsersAPI { impl Default for UsersAPI { fn default() -> Self { - Self { - config: configuration::Configuration::new(), - client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()).build(), - } + Self::with_config(configuration::Configuration::default()) } } @@ -187,9 +190,36 @@ impl UsersAPI { reqwest_client_builder = reqwest_client_builder.proxy(proxy); } - let middleware_client_builder = + let mut middleware_client_builder = reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + let client = middleware_client_builder.build(); + Self { config, client } } @@ -237,27 +267,85 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -314,20 +402,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -394,20 +501,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -476,20 +602,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -560,20 +705,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -645,20 +809,39 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -794,20 +977,39 @@ impl UsersAPI { local_req_builder.query(&[("filter[status]", &local_query_param.to_string())]); }; + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -875,27 +1077,85 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; @@ -969,27 +1229,85 @@ impl UsersAPI { let mut local_req_builder = local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + headers.insert("Accept", HeaderValue::from_static("application/json")); + // build user agent - local_req_builder = local_req_builder.header( - reqwest::header::USER_AGENT, - local_configuration.user_agent.clone(), - ); + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(configuration::DEFAULT_USER_AGENT.as_str()), + ) + } + }; // build auth if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { - local_req_builder = local_req_builder.header("DD-API-KEY", &local_key.key); + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); }; if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { - local_req_builder = local_req_builder.header("DD-APPLICATION-KEY", &local_key.key); + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); }; // build body parameters let output = Vec::new(); let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter); if body.serialize(&mut ser).is_ok() { - local_req_builder = local_req_builder.body(ser.into_inner()); + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } } + local_req_builder = local_req_builder.headers(headers); let local_req = local_req_builder.build()?; let local_resp = local_client.execute(local_req).await?; diff --git a/tests/main.rs b/tests/main.rs index 01f7f7edc..95aef7663 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -1,6 +1,6 @@ mod scenarios; -use cucumber::{cli, parser, runner, writer, World}; +use cucumber::{cli, parser, runner, writer, StatsWriter, World}; use lazy_static::lazy_static; use regex::Regex; use scenarios::fixtures::{ @@ -91,7 +91,7 @@ async fn main() { } } - cucumber + if cucumber .filter_run("tests/scenarios/features/".to_string(), move |_, _, sc| { let name_re = parsed_cli.re_filter.clone(); let name_match = name_re @@ -109,6 +109,10 @@ async fn main() { true } }) - .await; + .await + .execution_has_failed() + { + std::process::exit(1); + } } // right now it repeats failed steps, eventually write custom writer logic for repeating failed scenarios diff --git a/tests/scenarios/fixtures.rs b/tests/scenarios/fixtures.rs index 09e8bdcb5..5616b5334 100644 --- a/tests/scenarios/fixtures.rs +++ b/tests/scenarios/fixtures.rs @@ -54,7 +54,7 @@ pub struct DatadogWorld { pub parameters: HashMap, pub response: Response, pub api_name: Option, - pub api_instances: ApiInstances, + pub api_instances: Box, undo_operations: Vec, } @@ -175,6 +175,34 @@ pub async fn before_scenario( vcr_client_builder.with(middleware) } }; + + world.config.set_retry(true, 3); + + if world.config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(world.config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + vcr_client_builder = vcr_client_builder.with(retry_middleware); + } + world.http_client = Some(vcr_client_builder.build()); let escaped_name = NON_ALNUM_RE diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index db3a75ccd..394d5cf84 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -8048,13 +8048,12 @@ fn test_v1_upload_idp_for_org(world: &mut DatadogWorld, _parameters: &HashMap response, Err(error) => { @@ -10419,9 +10418,14 @@ fn test_v2_update_open_api(world: &mut DatadogWorld, _parameters: &HashMap