qubit_http/request/async_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 AsyncHeaderInjectorFuture<'a> = Pin<Box<dyn Future<Output = HttpResult<()>> + Send + 'a>>;
20type AsyncHeaderInjectorFn =
21 dyn for<'a> Fn(&'a mut HeaderMap) -> AsyncHeaderInjectorFuture<'a> + Send + Sync + 'static;
22
23/// Async header injector that can await external state (for example token refresh)
24/// before mutating outbound request headers.
25#[derive(Clone)]
26pub struct AsyncHeaderInjector {
27 /// Underlying async mutation callback.
28 inner: Arc<AsyncHeaderInjectorFn>,
29}
30
31impl std::fmt::Debug for AsyncHeaderInjector {
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("AsyncHeaderInjector")
41 .finish_non_exhaustive()
42 }
43}
44
45impl AsyncHeaderInjector {
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 [`AsyncHeaderInjector`].
53 pub fn new<F>(injector: F) -> Self
54 where
55 F: for<'a> Fn(&'a mut HeaderMap) -> AsyncHeaderInjectorFuture<'a> + Send + Sync + 'static,
56 {
57 Self {
58 inner: Arc::new(injector),
59 }
60 }
61
62 /// Applies this injector to `headers`.
63 ///
64 /// # Parameters
65 /// - `headers`: Header map to mutate.
66 ///
67 /// # Returns
68 /// `Ok(())` on success.
69 ///
70 /// # Errors
71 /// Propagates callback-provided [`crate::HttpError`].
72 pub async fn apply(&self, headers: &mut HeaderMap) -> HttpResult<()> {
73 (self.inner)(headers).await
74 }
75}