Skip to main content

qubit_http/request/
async_http_header_injector.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Async header injector abstraction for outgoing requests.
11
12use std::future::Future;
13use std::pin::Pin;
14use std::sync::Arc;
15
16use http::HeaderMap;
17
18use crate::HttpResult;
19
20type AsyncHttpHeaderInjectorFuture<'a> = Pin<Box<dyn Future<Output = HttpResult<()>> + Send + 'a>>;
21type AsyncHttpHeaderInjectorFn =
22    dyn for<'a> Fn(&'a mut HeaderMap) -> AsyncHttpHeaderInjectorFuture<'a> + Send + Sync + 'static;
23
24/// Async HTTP header injector that can await external state (for example token refresh)
25/// before mutating outbound request headers.
26#[derive(Clone)]
27pub struct AsyncHttpHeaderInjector {
28    /// Underlying async mutation callback.
29    inner: Arc<AsyncHttpHeaderInjectorFn>,
30}
31
32impl std::fmt::Debug for AsyncHttpHeaderInjector {
33    /// Formats this injector without exposing closure internals.
34    ///
35    /// # Parameters
36    /// - `f`: Formatter destination.
37    ///
38    /// # Returns
39    /// Formatting result.
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        f.debug_struct("AsyncHttpHeaderInjector")
42            .finish_non_exhaustive()
43    }
44}
45
46impl AsyncHttpHeaderInjector {
47    /// Creates an async header injector from a callback.
48    ///
49    /// # Parameters
50    /// - `injector`: Async callback that mutates `HeaderMap` and may fail.
51    ///
52    /// # Returns
53    /// New [`AsyncHttpHeaderInjector`].
54    pub fn new<F>(injector: F) -> Self
55    where
56        F: for<'a> Fn(&'a mut HeaderMap) -> AsyncHttpHeaderInjectorFuture<'a>
57            + Send
58            + Sync
59            + 'static,
60    {
61        Self {
62            inner: Arc::new(injector),
63        }
64    }
65
66    /// Applies this injector to `headers`.
67    ///
68    /// # Parameters
69    /// - `headers`: Header map to mutate.
70    ///
71    /// # Returns
72    /// `Ok(())` on success.
73    ///
74    /// # Errors
75    /// Propagates callback-provided [`crate::HttpError`].
76    pub async fn apply(&self, headers: &mut HeaderMap) -> HttpResult<()> {
77        (self.inner)(headers).await
78    }
79}