Skip to main content

qubit_http/request/
async_http_header_injector.rs

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