Skip to main content

rama_http/layer/set_header/request/
header.rs

1use crate::{HeaderName, HeaderValue, Request};
2use rama_http_headers::HeaderEncode;
3use std::fmt;
4use std::{
5    future::{Future, ready},
6    marker::PhantomData,
7};
8
9/// Trait for producing header values.
10///
11/// Used by [`SetRequestHeader`].
12///
13/// This trait is implemented for closures with the correct type signature. Typically users will
14/// not have to implement this trait for their own types.
15///
16/// It is also implemented directly for [`HeaderValue`]. When a fixed header value should be added
17/// to all responses, it can be supplied directly to the middleware.
18///
19/// [`SetRequestHeader`]: crate::layer::set_header::SetRequestHeader
20pub trait MakeHeaderValue<B>: Send + Sync + 'static {
21    /// Try to create a header value from the request or response.
22    fn make_header_value(
23        &self,
24        req: Request<B>,
25    ) -> impl Future<Output = (Request<B>, Option<HeaderValue>)> + Send + '_;
26}
27
28#[derive(Default)]
29/// Marker type to allow types which are [`MakeHeaderValue`] and
30/// also have a [`Default`] way to construct to let them be constructed
31/// on the fly. Useful alternative for cloning or using a function.
32pub struct MakeHeaderValueDefault<M>(PhantomData<fn(M)>);
33
34impl<M> MakeHeaderValueDefault<M> {
35    #[inline(always)]
36    pub(super) fn new() -> Self {
37        Self(PhantomData)
38    }
39}
40
41impl<M> fmt::Debug for MakeHeaderValueDefault<M> {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        f.debug_tuple("MakeHeaderValueDefault")
44            .field(&std::any::type_name::<M>())
45            .finish()
46    }
47}
48
49impl<M> Clone for MakeHeaderValueDefault<M> {
50    #[inline(always)]
51    fn clone(&self) -> Self {
52        Self::new()
53    }
54}
55
56impl<M, ReqBody> MakeHeaderValue<ReqBody> for MakeHeaderValueDefault<M>
57where
58    M: MakeHeaderValue<ReqBody> + Default,
59    ReqBody: Send + 'static,
60{
61    #[inline(always)]
62    async fn make_header_value(
63        &self,
64        req: Request<ReqBody>,
65    ) -> (Request<ReqBody>, Option<HeaderValue>) {
66        M::default().make_header_value(req).await
67    }
68}
69
70/// Wrapper used internally as part of making typed headers
71/// encode header values on the spot, when needed.
72#[derive(Debug, Clone, Default)]
73pub struct TypedHeaderAsMaker<H>(pub(super) H);
74
75/// Functional version of [`MakeHeaderValue`].
76pub trait MakeHeaderValueFn<B, A>: Send + Sync + 'static {
77    /// Try to create a header value from the request or response.
78    fn call(
79        &self,
80        req: Request<B>,
81    ) -> impl Future<Output = (Request<B>, Option<HeaderValue>)> + Send + '_;
82}
83
84impl<F, Fut, B> MakeHeaderValueFn<B, ()> for F
85where
86    B: Send + 'static,
87    F: Fn() -> Fut + Send + Sync + 'static,
88    Fut: Future<Output = Option<HeaderValue>> + Send + 'static,
89{
90    async fn call(&self, req: Request<B>) -> (Request<B>, Option<HeaderValue>) {
91        let maybe_value = self().await;
92        (req, maybe_value)
93    }
94}
95
96impl<F, Fut, B> MakeHeaderValueFn<B, ((), B)> for F
97where
98    B: Send + 'static,
99    F: Fn(Request<B>) -> Fut + Send + Sync + 'static,
100    Fut: Future<Output = (Request<B>, Option<HeaderValue>)> + Send + 'static,
101{
102    async fn call(&self, req: Request<B>) -> (Request<B>, Option<HeaderValue>) {
103        let (req, maybe_value) = self(req).await;
104        (req, maybe_value)
105    }
106}
107
108/// The public wrapper type for [`MakeHeaderValueFn`].
109pub struct BoxMakeHeaderValueFn<F, A> {
110    f: F,
111    _marker: PhantomData<fn(A) -> ()>,
112}
113
114impl<F, A> BoxMakeHeaderValueFn<F, A> {
115    /// Create a new [`BoxMakeHeaderValueFn`].
116    pub const fn new(f: F) -> Self {
117        Self {
118            f,
119            _marker: PhantomData,
120        }
121    }
122}
123
124impl<F, A> Clone for BoxMakeHeaderValueFn<F, A>
125where
126    F: Clone,
127{
128    fn clone(&self) -> Self {
129        Self {
130            f: self.f.clone(),
131            _marker: PhantomData,
132        }
133    }
134}
135
136impl<F, A> std::fmt::Debug for BoxMakeHeaderValueFn<F, A>
137where
138    F: std::fmt::Debug,
139{
140    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141        f.debug_struct("BoxMakeHeaderValueFn")
142            .field("f", &self.f)
143            .finish()
144    }
145}
146
147impl<B, A, F> MakeHeaderValue<B> for BoxMakeHeaderValueFn<F, A>
148where
149    A: Send + 'static,
150    F: MakeHeaderValueFn<B, A>,
151{
152    fn make_header_value(
153        &self,
154        req: Request<B>,
155    ) -> impl Future<Output = (Request<B>, Option<HeaderValue>)> + Send + '_ {
156        self.f.call(req)
157    }
158}
159
160impl<B, M> MakeHeaderValue<B> for Option<M>
161where
162    M: MakeHeaderValue<B> + Clone,
163    B: Send + 'static,
164{
165    async fn make_header_value(&self, req: Request<B>) -> (Request<B>, Option<HeaderValue>) {
166        match self {
167            Some(m) => m.make_header_value(req).await,
168            None => (req, None),
169        }
170    }
171}
172
173impl<B> MakeHeaderValue<B> for HeaderValue
174where
175    B: Send + 'static,
176{
177    fn make_header_value(
178        &self,
179        req: Request<B>,
180    ) -> impl Future<Output = (Request<B>, Option<Self>)> + Send + '_ {
181        ready((req, Some(self.clone())))
182    }
183}
184
185impl<B, H> MakeHeaderValue<B> for TypedHeaderAsMaker<H>
186where
187    B: Send + 'static,
188    H: HeaderEncode + Send + Sync + 'static,
189{
190    fn make_header_value(
191        &self,
192        req: Request<B>,
193    ) -> impl Future<Output = (Request<B>, Option<HeaderValue>)> + Send {
194        let maybe_value = self.0.encode_to_value();
195        ready((req, maybe_value))
196    }
197}
198
199#[derive(Debug, Clone, Copy)]
200pub(super) enum InsertHeaderMode {
201    Override,
202    Append,
203    IfNotPresent,
204}
205
206impl InsertHeaderMode {
207    pub(super) async fn apply<B, M>(
208        self,
209        header_name: &HeaderName,
210        req: Request<B>,
211        make: &M,
212    ) -> Request<B>
213    where
214        B: Send + 'static,
215        M: MakeHeaderValue<B>,
216    {
217        match self {
218            Self::Override => {
219                let (mut req, maybe_value) = make.make_header_value(req).await;
220                if let Some(value) = maybe_value {
221                    req.headers_mut().insert(header_name.clone(), value);
222                }
223                req
224            }
225            Self::IfNotPresent => {
226                if !req.headers().contains_key(header_name) {
227                    let (mut req, maybe_value) = make.make_header_value(req).await;
228                    if let Some(value) = maybe_value {
229                        req.headers_mut().insert(header_name.clone(), value);
230                    }
231                    req
232                } else {
233                    req
234                }
235            }
236            Self::Append => {
237                let (mut req, maybe_value) = make.make_header_value(req).await;
238                if let Some(value) = maybe_value {
239                    req.headers_mut().append(header_name.clone(), value);
240                }
241                req
242            }
243        }
244    }
245}