From 54f84a9e4075939c84ec5ef454e42ef7c4c20f0e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 27 Feb 2026 16:52:52 +0000 Subject: [PATCH] feat(middleware): add BearerTokenMiddleware for OAuth2 bearer token injection --- Cargo.toml | 2 ++ src/datadog/configuration.rs | 9 ++++++++ src/datadog/middleware.rs | 41 ++++++++++++++++++++++++++++++++++++ src/datadog/mod.rs | 3 +++ 4 files changed, 55 insertions(+) create mode 100644 src/datadog/middleware.rs diff --git a/Cargo.toml b/Cargo.toml index cd88c4f87..3da5b20d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,8 @@ version = "0.27.0" [dependencies] async-stream = "0.3.5" +async-trait = "0.1" +task-local-extensions = "0.1" chrono = {version = "0.4.31", features = ["serde"] } flate2 = "1.0.28" form-data-builder = "1.0.1" diff --git a/src/datadog/configuration.rs b/src/datadog/configuration.rs index cb1af6230..7464e3a41 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -53,6 +53,10 @@ pub struct Configuration { pub proxy_url: Option, pub enable_retry: bool, pub max_retries: u32, + /// OAuth2 bearer token. When set, `BearerTokenMiddleware` will inject + /// `Authorization: Bearer ` on every request. + /// Populated automatically from the `DD_ACCESS_TOKEN` environment variable. + pub bearer_token: Option, } impl Configuration { @@ -109,6 +113,10 @@ impl Configuration { self.auth_keys.insert(operation_str.to_string(), api_key); } + pub fn set_bearer_token(&mut self, token: String) { + self.bearer_token = Some(token); + } + pub fn set_proxy_url(&mut self, proxy_url: Option) { self.proxy_url = proxy_url; } @@ -377,6 +385,7 @@ impl Default for Configuration { proxy_url: None, enable_retry: false, max_retries: 3, + bearer_token: env::var("DD_ACCESS_TOKEN").ok(), } } } diff --git a/src/datadog/middleware.rs b/src/datadog/middleware.rs new file mode 100644 index 000000000..587443950 --- /dev/null +++ b/src/datadog/middleware.rs @@ -0,0 +1,41 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +//! Bearer token middleware for OAuth2 authentication. +//! +//! Since the generated API structs only support API key auth natively, this +//! middleware allows injecting an OAuth2 bearer token at the HTTP layer when +//! using [`with_client_and_config`](crate::datadogV2::api_logs::LogsAPI::with_client_and_config). + +use async_trait::async_trait; +use reqwest_middleware::{Middleware, Next, Result}; +use task_local_extensions::Extensions; + +/// Injects `Authorization: Bearer ` into every outgoing request. +/// +/// Because the DD API client adds `DD-API-KEY` / `DD-APPLICATION-KEY` headers +/// inside each `_with_http_info` method, this middleware runs *after* those +/// headers are set. The `Authorization` header is distinct so there is no +/// conflict — both sets of headers end up on the request. +pub struct BearerTokenMiddleware { + pub token: String, +} + +#[async_trait] +impl Middleware for BearerTokenMiddleware { + async fn handle( + &self, + mut req: reqwest::Request, + extensions: &mut Extensions, + next: Next<'_>, + ) -> Result { + req.headers_mut().insert( + reqwest::header::AUTHORIZATION, + format!("Bearer {}", self.token) + .parse() + .expect("bearer token is valid header value"), + ); + next.run(req, extensions).await + } +} diff --git a/src/datadog/mod.rs b/src/datadog/mod.rs index e70ecb935..5384de09e 100644 --- a/src/datadog/mod.rs +++ b/src/datadog/mod.rs @@ -5,6 +5,9 @@ use std::fmt; mod configuration; pub use configuration::{APIKey, Configuration, DEFAULT_USER_AGENT}; +pub mod middleware; +pub use middleware::BearerTokenMiddleware; + #[derive(Debug, Clone)] pub struct ResponseContent { pub status: reqwest::StatusCode,