Skip to main content

rama_http/layer/set_header/response/
header.rs

1use crate::{HeaderName, HeaderValue, Request, Response};
2use rama_http_headers::HeaderEncode;
3use std::fmt;
4use std::{
5    future::{Future, ready},
6    marker::PhantomData,
7};
8
9/// Trait for preparing a maker ([`MakeHeaderValue`]) that will be used
10/// to actually create the [`HeaderValue`] when desired.
11///
12/// The reason why this is split in two parts for responses is because
13/// the context is consumed by the inner service producting the response
14/// to which the header (maybe) will be attached to. In order to not
15/// clone the entire `Context` and its `State` it is therefore better
16/// to let the implementer decide what state is to be cloned and which not.
17///
18/// E.g. for a static Header value one might not need any state or context at all,
19/// which would make it pretty wastefull if we would for such cases clone
20/// these stateful datastructures anyhow.
21///
22/// Most users will however not have to worry about this Trait or why it is there,
23/// as the trait is implemented already for functions, closures and HeaderValues.
24pub trait MakeHeaderValueFactory<ReqBody, ResBody>: Send + Sync + 'static {
25    /// Maker that _can_ be produced by this Factory.
26    type Maker: MakeHeaderValue<ResBody>;
27
28    /// Try to create a header value from the request or response.
29    fn make_header_value_maker(
30        &self,
31        request: Request<ReqBody>,
32    ) -> impl Future<Output = (Request<ReqBody>, Self::Maker)> + Send + '_;
33}
34
35/// Trait for producing header values, created by a `MakeHeaderValueFactory`.
36///
37/// Used by [`SetResponseHeader`].
38///
39/// This trait is implemented for closures with the correct type signature. Typically users will
40/// not have to implement this trait for their own types.
41///
42/// It is also implemented directly for [`HeaderValue`]. When a fixed header value should be added
43/// to all responses, it can be supplied directly to the middleware.
44///
45/// [`SetResponseHeader`]: crate::layer::set_header::SetResponseHeader
46pub trait MakeHeaderValue<B>: Send + Sync + 'static {
47    /// Try to create a header value from the request or response.
48    fn make_header_value(
49        self,
50        response: Response<B>,
51    ) -> impl Future<Output = (Response<B>, Option<HeaderValue>)> + Send;
52}
53
54impl<B, M> MakeHeaderValue<B> for Option<M>
55where
56    M: MakeHeaderValue<B> + Clone,
57    B: Send + 'static,
58{
59    async fn make_header_value(self, response: Response<B>) -> (Response<B>, Option<HeaderValue>) {
60        match self {
61            Some(m) => m.make_header_value(response).await,
62            None => (response, None),
63        }
64    }
65}
66
67impl<B> MakeHeaderValue<B> for HeaderValue
68where
69    B: Send + 'static,
70{
71    fn make_header_value(
72        self,
73        response: Response<B>,
74    ) -> impl Future<Output = (Response<B>, Option<Self>)> + Send {
75        ready((response, Some(self)))
76    }
77}
78
79impl<B, H> MakeHeaderValue<B> for TypedHeaderAsMaker<H>
80where
81    B: Send + 'static,
82    H: HeaderEncode + Send + Sync + 'static,
83{
84    fn make_header_value(
85        self,
86        response: Response<B>,
87    ) -> impl Future<Output = (Response<B>, Option<HeaderValue>)> + Send {
88        let maybe_value = self.0.encode_to_value();
89        ready((response, maybe_value))
90    }
91}
92
93impl<ReqBody, ResBody> MakeHeaderValueFactory<ReqBody, ResBody> for HeaderValue
94where
95    ReqBody: Send + 'static,
96    ResBody: Send + 'static,
97{
98    type Maker = Self;
99
100    fn make_header_value_maker(
101        &self,
102        req: Request<ReqBody>,
103    ) -> impl Future<Output = (Request<ReqBody>, Self::Maker)> + Send + '_ {
104        ready((req, self.clone()))
105    }
106}
107
108impl<ReqBody, ResBody> MakeHeaderValueFactory<ReqBody, ResBody> for Option<HeaderValue>
109where
110    ReqBody: Send + 'static,
111    ResBody: Send + 'static,
112{
113    type Maker = Self;
114
115    fn make_header_value_maker(
116        &self,
117        req: Request<ReqBody>,
118    ) -> impl Future<Output = (Request<ReqBody>, Self::Maker)> + Send + '_ {
119        ready((req, self.clone()))
120    }
121}
122
123#[derive(Default)]
124/// Marker type to allow types which are [`MakeHeaderValue`] and
125/// also have a [`Default`] way to construct to let them be constructed
126/// on the fly. Useful alternative for cloning or using a function.
127pub struct MakeHeaderValueDefault<M>(PhantomData<fn(M)>);
128
129impl<M> MakeHeaderValueDefault<M> {
130    #[inline(always)]
131    pub(super) fn new() -> Self {
132        Self(PhantomData)
133    }
134}
135
136impl<M> fmt::Debug for MakeHeaderValueDefault<M> {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        f.debug_tuple("MakeHeaderValueDefault")
139            .field(&std::any::type_name::<M>())
140            .finish()
141    }
142}
143
144impl<M> Clone for MakeHeaderValueDefault<M> {
145    #[inline(always)]
146    fn clone(&self) -> Self {
147        Self::new()
148    }
149}
150
151impl<M, ReqBody, ResBody> MakeHeaderValueFactory<ReqBody, ResBody> for MakeHeaderValueDefault<M>
152where
153    M: MakeHeaderValue<ResBody> + Default,
154    ReqBody: Send + 'static,
155    ResBody: Send + 'static,
156{
157    type Maker = M;
158
159    fn make_header_value_maker(
160        &self,
161        req: Request<ReqBody>,
162    ) -> impl Future<Output = (Request<ReqBody>, Self::Maker)> + Send + '_ {
163        ready((req, M::default()))
164    }
165}
166
167/// Wrapper used internally as part of making typed headers
168/// encode header values on the spot, when needed.
169#[derive(Debug, Clone, Default)]
170pub struct TypedHeaderAsMaker<H>(pub(super) H);
171
172/// Functional version of [`MakeHeaderValue`].
173pub trait MakeHeaderValueFactoryFn<ReqBody, ResBody, A>: Send + Sync + 'static {
174    type Maker: MakeHeaderValue<ResBody>;
175
176    /// Try to create a header value from the request or response.
177    fn call(
178        &self,
179        request: Request<ReqBody>,
180    ) -> impl Future<Output = (Request<ReqBody>, Self::Maker)> + Send + '_;
181}
182
183impl<F, Fut, ReqBody, ResBody, M> MakeHeaderValueFactoryFn<ReqBody, ResBody, ()> for F
184where
185    ReqBody: Send + 'static,
186    ResBody: Send + 'static,
187    M: MakeHeaderValue<ResBody>,
188    F: Fn() -> Fut + Send + Sync + 'static,
189    Fut: Future<Output = M> + Send + 'static,
190    M: MakeHeaderValue<ResBody>,
191{
192    type Maker = M;
193
194    async fn call(&self, request: Request<ReqBody>) -> (Request<ReqBody>, M) {
195        let maker = self().await;
196        (request, maker)
197    }
198}
199
200impl<F, Fut, ReqBody, ResBody, M> MakeHeaderValueFactoryFn<ReqBody, ResBody, ((), Request<ReqBody>)>
201    for F
202where
203    ReqBody: Send + 'static,
204    ResBody: Send + 'static,
205    M: MakeHeaderValue<ResBody>,
206    F: Fn(Request<ReqBody>) -> Fut + Send + Sync + 'static,
207    Fut: Future<Output = (Request<ReqBody>, M)> + Send + 'static,
208    M: MakeHeaderValue<ResBody>,
209{
210    type Maker = M;
211
212    async fn call(&self, request: Request<ReqBody>) -> (Request<ReqBody>, M) {
213        let (request, maker) = self(request).await;
214        (request, maker)
215    }
216}
217
218/// The public wrapper type for [`MakeHeaderValueFactoryFn`].
219pub struct BoxMakeHeaderValueFactoryFn<F, A> {
220    f: F,
221    _marker: PhantomData<fn(A) -> ()>,
222}
223
224impl<F, A> BoxMakeHeaderValueFactoryFn<F, A> {
225    /// Create a new [`BoxMakeHeaderValueFactoryFn`].
226    pub const fn new(f: F) -> Self {
227        Self {
228            f,
229            _marker: PhantomData,
230        }
231    }
232}
233
234impl<F, A> Clone for BoxMakeHeaderValueFactoryFn<F, A>
235where
236    F: Clone,
237{
238    fn clone(&self) -> Self {
239        Self {
240            f: self.f.clone(),
241            _marker: PhantomData,
242        }
243    }
244}
245
246impl<F, A> std::fmt::Debug for BoxMakeHeaderValueFactoryFn<F, A>
247where
248    F: std::fmt::Debug,
249{
250    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251        f.debug_struct("BoxMakeHeaderValueFn")
252            .field("f", &self.f)
253            .finish()
254    }
255}
256
257impl<ReqBody, ResBody, A, F> MakeHeaderValueFactory<ReqBody, ResBody>
258    for BoxMakeHeaderValueFactoryFn<F, A>
259where
260    A: Send + 'static,
261    F: MakeHeaderValueFactoryFn<ReqBody, ResBody, A>,
262{
263    type Maker = F::Maker;
264
265    fn make_header_value_maker(
266        &self,
267        request: Request<ReqBody>,
268    ) -> impl Future<Output = (Request<ReqBody>, Self::Maker)> + Send + '_ {
269        self.f.call(request)
270    }
271}
272
273/// Functional version of [`MakeHeaderValue`],
274/// to make it easier to create a (response) header maker
275/// directly from a response.
276pub trait MakeHeaderValueFn<B, A>: Send + Sync + 'static {
277    /// Try to create a header value from the request or response.
278    fn call(
279        self,
280        response: Response<B>,
281    ) -> impl Future<Output = (Response<B>, Option<HeaderValue>)> + Send;
282}
283
284impl<F, Fut, B> MakeHeaderValueFn<B, ()> for F
285where
286    B: Send + 'static,
287    F: FnOnce() -> Fut + Send + Sync + 'static,
288    Fut: Future<Output = Option<HeaderValue>> + Send + 'static,
289{
290    async fn call(self, response: Response<B>) -> (Response<B>, Option<HeaderValue>) {
291        let maybe_value = self().await;
292        (response, maybe_value)
293    }
294}
295
296impl<F, Fut, B> MakeHeaderValueFn<B, Response<B>> for F
297where
298    B: Send + 'static,
299    F: FnOnce(Response<B>) -> Fut + Send + Sync + 'static,
300    Fut: Future<Output = (Response<B>, Option<HeaderValue>)> + Send + 'static,
301{
302    async fn call(self, response: Response<B>) -> (Response<B>, Option<HeaderValue>) {
303        let (response, maybe_value) = self(response).await;
304        (response, maybe_value)
305    }
306}
307
308/// The public wrapper type for [`MakeHeaderValueFn`].
309pub struct BoxMakeHeaderValueFn<F, A> {
310    f: F,
311    _marker: PhantomData<fn(A) -> ()>,
312}
313
314impl<F, A> BoxMakeHeaderValueFn<F, A> {
315    /// Create a new [`BoxMakeHeaderValueFn`].
316    pub const fn new(f: F) -> Self {
317        Self {
318            f,
319            _marker: PhantomData,
320        }
321    }
322}
323
324impl<F, A> Clone for BoxMakeHeaderValueFn<F, A>
325where
326    F: Clone,
327{
328    fn clone(&self) -> Self {
329        Self {
330            f: self.f.clone(),
331            _marker: PhantomData,
332        }
333    }
334}
335
336impl<F, A> std::fmt::Debug for BoxMakeHeaderValueFn<F, A>
337where
338    F: std::fmt::Debug,
339{
340    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
341        f.debug_struct("BoxMakeHeaderValueFn")
342            .field("f", &self.f)
343            .finish()
344    }
345}
346
347impl<B, A, F> MakeHeaderValue<B> for BoxMakeHeaderValueFn<F, A>
348where
349    A: Send + 'static,
350    F: MakeHeaderValueFn<B, A>,
351{
352    fn make_header_value(
353        self,
354        response: Response<B>,
355    ) -> impl Future<Output = (Response<B>, Option<HeaderValue>)> + Send {
356        self.f.call(response)
357    }
358}
359
360impl<F, Fut, ReqBody, ResBody> MakeHeaderValueFactoryFn<ReqBody, ResBody, ((), (), ())> for F
361where
362    ReqBody: Send + 'static,
363    ResBody: Send + 'static,
364    F: Fn() -> Fut + Clone + Send + Sync + 'static,
365    Fut: Future<Output = Option<HeaderValue>> + Send + 'static,
366{
367    type Maker = BoxMakeHeaderValueFn<F, ()>;
368
369    async fn call(&self, request: Request<ReqBody>) -> (Request<ReqBody>, Self::Maker) {
370        let maker = self.clone();
371        (request, BoxMakeHeaderValueFn::new(maker))
372    }
373}
374
375impl<F, Fut, ReqBody, ResBody>
376    MakeHeaderValueFactoryFn<ReqBody, ResBody, ((), (), Response<ResBody>)> for F
377where
378    ReqBody: Send + 'static,
379    ResBody: Send + 'static,
380    F: Fn(Response<ResBody>) -> Fut + Clone + Send + Sync + 'static,
381    Fut: Future<Output = (Response<ResBody>, Option<HeaderValue>)> + Send + 'static,
382{
383    type Maker = BoxMakeHeaderValueFn<F, Response<ResBody>>;
384
385    async fn call(&self, request: Request<ReqBody>) -> (Request<ReqBody>, Self::Maker) {
386        let maker = self.clone();
387        (request, BoxMakeHeaderValueFn::new(maker))
388    }
389}
390
391#[derive(Debug, Clone, Copy)]
392pub(super) enum InsertHeaderMode {
393    Override,
394    Append,
395    IfNotPresent,
396}
397
398impl InsertHeaderMode {
399    pub(super) async fn apply<B, M>(
400        self,
401        header_name: &HeaderName,
402        response: Response<B>,
403        make: M,
404    ) -> Response<B>
405    where
406        B: Send + 'static,
407        M: MakeHeaderValue<B>,
408    {
409        match self {
410            Self::Override => {
411                let (mut response, maybe_value) = make.make_header_value(response).await;
412                if let Some(value) = maybe_value {
413                    response.headers_mut().insert(header_name.clone(), value);
414                }
415                response
416            }
417            Self::IfNotPresent => {
418                if !response.headers().contains_key(header_name) {
419                    let (mut response, maybe_value) = make.make_header_value(response).await;
420                    if let Some(value) = maybe_value {
421                        response.headers_mut().insert(header_name.clone(), value);
422                    }
423                    response
424                } else {
425                    response
426                }
427            }
428            Self::Append => {
429                let (mut response, maybe_value) = make.make_header_value(response).await;
430                if let Some(value) = maybe_value {
431                    response.headers_mut().append(header_name.clone(), value);
432                }
433                response
434            }
435        }
436    }
437}