Skip to main content

rama_http/layer/set_header/request/
mod.rs

1//! Set a header on the request.
2//!
3//! The header value to be set may be provided as a fixed value when the
4//! middleware is constructed, or determined dynamically based on the request
5//! by a closure. See the [`MakeHeaderValue`] trait for details.
6//!
7//! # Example
8//!
9//! Setting a header from a fixed value provided when the middleware is constructed:
10//!
11//! ```
12//! use rama_http::layer::set_header::SetRequestHeaderLayer;
13//! use rama_http::{Body, Request, Response, header::{self, HeaderValue}};
14//! use rama_core::service::service_fn;
15//! use rama_core::{Service, Layer};
16//! use rama_core::error::BoxError;
17//!
18//! # #[tokio::main]
19//! # async fn main() -> Result<(), BoxError> {
20//! # let http_client = service_fn(async |_: Request| {
21//! #     Ok::<_, std::convert::Infallible>(Response::new(Body::empty()))
22//! # });
23//! #
24//! let mut svc = (
25//!     // Layer that sets `User-Agent: my very cool proxy` on requests.
26//!     //
27//!     // `if_not_present` will only insert the header if it does not already
28//!     // have a value.
29//!     SetRequestHeaderLayer::if_not_present(
30//!         header::USER_AGENT,
31//!         HeaderValue::from_static("my very cool proxy"),
32//!     ),
33//! ).into_layer(http_client);
34//!
35//! let request = Request::new(Body::empty());
36//!
37//! let response = svc.serve(request).await?;
38//! #
39//! # Ok(())
40//! # }
41//! ```
42//!
43//! Setting a header based on a value determined dynamically from the request:
44//!
45//! ```
46//! use rama_http::{Body, Request, Response, header::{self, HeaderValue}};
47//! use rama_http::layer::set_header::SetRequestHeaderLayer;
48//! use rama_core::service::service_fn;
49//! use rama_core::{Service, Layer};
50//! use rama_core::error::BoxError;
51//!
52//! # #[tokio::main]
53//! # async fn main() -> Result<(), BoxError> {
54//! # let http_client = service_fn(async || {
55//! #     Ok::<_, std::convert::Infallible>(Response::new(Body::empty()))
56//! # });
57//! fn date_header_value() -> HeaderValue {
58//!     // ...
59//!     # HeaderValue::from_static("now")
60//! }
61//!
62//! let mut svc = (
63//!     // Layer that sets `Date` to the current date and time.
64//!     //
65//!     // `overriding` will insert the header and override any previous values it
66//!     // may have.
67//!     SetRequestHeaderLayer::overriding_fn(
68//!         header::DATE,
69//!         async || {
70//!             Some(date_header_value())
71//!         }
72//!     ),
73//! ).into_layer(http_client);
74//!
75//! let request = Request::new(Body::default());
76//!
77//! let response = svc.serve(request).await?;
78//! #
79//! # Ok(())
80//! # }
81//! ```
82
83use crate::{HeaderValue, Request, Response, header::HeaderName, headers::HeaderEncode};
84use rama_core::{Layer, Service};
85use rama_http_headers::TypedHeader;
86use rama_utils::macros::define_inner_service_accessors;
87use std::fmt;
88
89mod header;
90use header::InsertHeaderMode;
91
92pub use header::{
93    BoxMakeHeaderValueFn, MakeHeaderValue, MakeHeaderValueDefault, MakeHeaderValueFn,
94    TypedHeaderAsMaker,
95};
96
97/// Layer that applies [`SetRequestHeader`] which adds a request header.
98///
99/// See [`SetRequestHeader`] for more details.
100pub struct SetRequestHeaderLayer<M> {
101    header_name: HeaderName,
102    make: M,
103    mode: InsertHeaderMode,
104}
105
106impl<M> fmt::Debug for SetRequestHeaderLayer<M> {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        f.debug_struct("SetRequestHeaderLayer")
109            .field("header_name", &self.header_name)
110            .field("mode", &self.mode)
111            .field("make", &std::any::type_name::<M>())
112            .finish()
113    }
114}
115
116impl<M> SetRequestHeaderLayer<M> {
117    /// Create a new [`SetRequestHeaderLayer`].
118    ///
119    /// If a previous value exists for the same header, it is removed and replaced with the new
120    /// header value.
121    #[inline(always)]
122    pub fn overriding(header_name: HeaderName, make: M) -> Self {
123        Self::new(header_name, make, InsertHeaderMode::Override)
124    }
125
126    /// Create a new [`SetRequestHeaderLayer`].
127    ///
128    /// The new header is always added, preserving any existing values. If previous values exist,
129    /// the header will have multiple values.
130    #[inline(always)]
131    pub fn appending(header_name: HeaderName, make: M) -> Self {
132        Self::new(header_name, make, InsertHeaderMode::Append)
133    }
134
135    /// Create a new [`SetRequestHeaderLayer`].
136    ///
137    /// If a previous value exists for the header, the new value is not inserted.
138    #[inline(always)]
139    pub fn if_not_present(header_name: HeaderName, make: M) -> Self {
140        Self::new(header_name, make, InsertHeaderMode::IfNotPresent)
141    }
142
143    fn new(header_name: HeaderName, make: M, mode: InsertHeaderMode) -> Self {
144        Self {
145            make,
146            header_name,
147            mode,
148        }
149    }
150}
151
152impl SetRequestHeaderLayer<Option<HeaderValue>> {
153    /// Create a new [`SetRequestHeaderLayer`] from a typed [`HeaderEncode`].
154    ///
155    /// See [`SetRequestHeaderLayer::overriding`] for more details.
156    #[inline(always)]
157    pub fn overriding_typed<H: HeaderEncode>(header: H) -> Self {
158        Self::overriding(H::name().clone(), header.encode_to_value())
159    }
160
161    /// Create a new [`SetRequestHeaderLayer`] from a typed [`HeaderEncode`].
162    ///
163    /// See [`SetRequestHeaderLayer::appending`] for more details.
164    #[inline(always)]
165    pub fn appending_typed<H: HeaderEncode>(header: H) -> Self {
166        Self::appending(H::name().clone(), header.encode_to_value())
167    }
168
169    /// Create a new [`SetRequestHeaderLayer`] from a typed [`HeaderEncode`].
170    ///
171    /// See [`SetRequestHeaderLayer::if_not_present`] for more details.
172    #[inline(always)]
173    pub fn if_not_present_typed<H: HeaderEncode>(header: H) -> Self {
174        Self::if_not_present(H::name().clone(), header.encode_to_value())
175    }
176}
177
178impl<F, A> SetRequestHeaderLayer<BoxMakeHeaderValueFn<F, A>> {
179    /// Create a new [`SetRequestHeaderLayer`] from a [`header::MakeHeaderValueFn`].
180    ///
181    /// See [`SetRequestHeaderLayer::overriding`] for more details.
182    #[inline(always)]
183    pub fn overriding_fn(header_name: HeaderName, make_fn: F) -> Self {
184        Self::new(
185            header_name,
186            BoxMakeHeaderValueFn::new(make_fn),
187            InsertHeaderMode::Override,
188        )
189    }
190
191    /// Create a new [`SetRequestHeaderLayer`] from a [`header::MakeHeaderValueFn`].
192    ///
193    /// See [`SetRequestHeaderLayer::appending`] for more details.
194    #[inline(always)]
195    pub fn appending_fn(header_name: HeaderName, make_fn: F) -> Self {
196        Self::new(
197            header_name,
198            BoxMakeHeaderValueFn::new(make_fn),
199            InsertHeaderMode::Append,
200        )
201    }
202
203    /// Create a new [`SetRequestHeaderLayer`] from a [`header::MakeHeaderValueFn`].
204    ///
205    /// See [`SetRequestHeaderLayer::if_not_present`] for more details.
206    #[inline(always)]
207    pub fn if_not_present_fn(header_name: HeaderName, make_fn: F) -> Self {
208        Self::new(
209            header_name,
210            BoxMakeHeaderValueFn::new(make_fn),
211            InsertHeaderMode::IfNotPresent,
212        )
213    }
214}
215
216impl<M> SetRequestHeaderLayer<M> {
217    /// Create a new [`SetRequestHeaderLayer`] from a [`Default`] [`MakeHeaderValue`].
218    ///
219    /// See [`SetRequestHeaderLayer::overriding`] for more details.
220    #[inline(always)]
221    pub fn overriding_default(
222        header_name: HeaderName,
223    ) -> SetRequestHeaderLayer<MakeHeaderValueDefault<M>> {
224        SetRequestHeaderLayer::new(
225            header_name,
226            MakeHeaderValueDefault::new(),
227            InsertHeaderMode::Override,
228        )
229    }
230
231    /// Create a new [`SetRequestHeaderLayer`] from a [`Default`] [`MakeHeaderValue`].
232    ///
233    /// See [`SetRequestHeaderLayer::appending`] for more details.
234    #[inline(always)]
235    pub fn appending_default(
236        header_name: HeaderName,
237    ) -> SetRequestHeaderLayer<MakeHeaderValueDefault<M>> {
238        SetRequestHeaderLayer::new(
239            header_name,
240            MakeHeaderValueDefault::new(),
241            InsertHeaderMode::Append,
242        )
243    }
244
245    /// Create a new [`SetRequestHeaderLayer`] from a [`Default`] [`MakeHeaderValue`].
246    ///
247    /// See [`SetRequestHeaderLayer::if_not_present`] for more details.
248    #[inline(always)]
249    pub fn if_not_present_default(
250        header_name: HeaderName,
251    ) -> SetRequestHeaderLayer<MakeHeaderValueDefault<M>> {
252        SetRequestHeaderLayer::new(
253            header_name,
254            MakeHeaderValueDefault::new(),
255            InsertHeaderMode::IfNotPresent,
256        )
257    }
258}
259
260impl<M: TypedHeader> SetRequestHeaderLayer<M> {
261    /// Create a new [`SetRequestHeaderLayer`] from a [`Default`] [`TypedHeader`].
262    ///
263    /// See [`SetRequestHeaderLayer::overriding`] for more details.
264    #[inline(always)]
265    #[must_use]
266    pub fn overriding_default_typed()
267    -> SetRequestHeaderLayer<MakeHeaderValueDefault<TypedHeaderAsMaker<M>>> {
268        SetRequestHeaderLayer::new(
269            M::name().clone(),
270            MakeHeaderValueDefault::new(),
271            InsertHeaderMode::Override,
272        )
273    }
274
275    /// Create a new [`SetRequestHeaderLayer`] from a [`Default`] [`TypedHeader`].
276    ///
277    /// See [`SetRequestHeaderLayer::appending`] for more details.
278    #[inline(always)]
279    #[must_use]
280    pub fn appending_default_typed()
281    -> SetRequestHeaderLayer<MakeHeaderValueDefault<TypedHeaderAsMaker<M>>> {
282        SetRequestHeaderLayer::new(
283            M::name().clone(),
284            MakeHeaderValueDefault::new(),
285            InsertHeaderMode::Append,
286        )
287    }
288
289    /// Create a new [`SetRequestHeaderLayer`] from a [`Default`] [`TypedHeader`].
290    ///
291    /// See [`SetRequestHeaderLayer::if_not_present`] for more details.
292    #[inline(always)]
293    #[must_use]
294    pub fn if_not_present_default_typed()
295    -> SetRequestHeaderLayer<MakeHeaderValueDefault<TypedHeaderAsMaker<M>>> {
296        SetRequestHeaderLayer::new(
297            M::name().clone(),
298            MakeHeaderValueDefault::new(),
299            InsertHeaderMode::IfNotPresent,
300        )
301    }
302}
303
304impl<S, M> Layer<S> for SetRequestHeaderLayer<M>
305where
306    M: Clone,
307{
308    type Service = SetRequestHeader<S, M>;
309
310    fn layer(&self, inner: S) -> Self::Service {
311        SetRequestHeader {
312            inner,
313            header_name: self.header_name.clone(),
314            make: self.make.clone(),
315            mode: self.mode,
316        }
317    }
318
319    fn into_layer(self, inner: S) -> Self::Service {
320        SetRequestHeader {
321            inner,
322            header_name: self.header_name,
323            make: self.make,
324            mode: self.mode,
325        }
326    }
327}
328
329impl<M> Clone for SetRequestHeaderLayer<M>
330where
331    M: Clone,
332{
333    fn clone(&self) -> Self {
334        Self {
335            make: self.make.clone(),
336            header_name: self.header_name.clone(),
337            mode: self.mode,
338        }
339    }
340}
341
342/// Middleware that sets a header on the request.
343#[derive(Clone)]
344pub struct SetRequestHeader<S, M> {
345    inner: S,
346    header_name: HeaderName,
347    make: M,
348    mode: InsertHeaderMode,
349}
350
351impl<S, H: HeaderEncode> SetRequestHeader<S, TypedHeaderAsMaker<H>> {
352    /// Create a new [`SetRequestHeader`] using a typed header.
353    ///
354    /// If a previous value exists for the same header, it is removed and replaced with the new
355    /// header value.
356    pub fn overriding_typed(inner: S, header: H) -> Self {
357        Self::overriding(inner, H::name().clone(), TypedHeaderAsMaker(header))
358    }
359
360    /// Create a new [`SetRequestHeader`] using a typed header.
361    ///
362    /// The new header is always added, preserving any existing values. If previous values exist,
363    /// the header will have multiple values.
364    pub fn appending_typed(inner: S, header: H) -> Self {
365        Self::appending(inner, H::name().clone(), TypedHeaderAsMaker(header))
366    }
367
368    /// Create a new [`SetRequestHeader`] using a typed header.
369    ///
370    /// If a previous value exists for the header, the new value is not inserted.
371    pub fn if_not_present_typed(inner: S, header: H) -> Self {
372        Self::if_not_present(inner, H::name().clone(), TypedHeaderAsMaker(header))
373    }
374}
375
376impl<S, M> SetRequestHeader<S, M> {
377    /// Create a new [`SetRequestHeader`].
378    ///
379    /// If a previous value exists for the same header, it is removed and replaced with the new
380    /// header value.
381    pub fn overriding(inner: S, header_name: HeaderName, make: M) -> Self {
382        Self::new(inner, header_name, make, InsertHeaderMode::Override)
383    }
384
385    /// Create a new [`SetRequestHeader`].
386    ///
387    /// The new header is always added, preserving any existing values. If previous values exist,
388    /// the header will have multiple values.
389    pub fn appending(inner: S, header_name: HeaderName, make: M) -> Self {
390        Self::new(inner, header_name, make, InsertHeaderMode::Append)
391    }
392
393    /// Create a new [`SetRequestHeader`].
394    ///
395    /// If a previous value exists for the header, the new value is not inserted.
396    pub fn if_not_present(inner: S, header_name: HeaderName, make: M) -> Self {
397        Self::new(inner, header_name, make, InsertHeaderMode::IfNotPresent)
398    }
399
400    fn new(inner: S, header_name: HeaderName, make: M, mode: InsertHeaderMode) -> Self {
401        Self {
402            inner,
403            header_name,
404            make,
405            mode,
406        }
407    }
408
409    define_inner_service_accessors!();
410}
411
412impl<S, F, A> SetRequestHeader<S, BoxMakeHeaderValueFn<F, A>> {
413    /// Create a new [`SetRequestHeader`] from a [`header::MakeHeaderValueFn`].
414    ///
415    /// See [`SetRequestHeader::overriding`] for more details.
416    pub fn overriding_fn(inner: S, header_name: HeaderName, make_fn: F) -> Self {
417        Self::new(
418            inner,
419            header_name,
420            BoxMakeHeaderValueFn::new(make_fn),
421            InsertHeaderMode::Override,
422        )
423    }
424
425    /// Create a new [`SetRequestHeader`] from a [`header::MakeHeaderValueFn`].
426    ///
427    /// See [`SetRequestHeader::appending`] for more details.
428    pub fn appending_fn(inner: S, header_name: HeaderName, make_fn: F) -> Self {
429        Self::new(
430            inner,
431            header_name,
432            BoxMakeHeaderValueFn::new(make_fn),
433            InsertHeaderMode::Append,
434        )
435    }
436
437    /// Create a new [`SetRequestHeader`] from a [`header::MakeHeaderValueFn`].
438    ///
439    /// See [`SetRequestHeader::if_not_present`] for more details.
440    pub fn if_not_present_fn(inner: S, header_name: HeaderName, make_fn: F) -> Self {
441        Self::new(
442            inner,
443            header_name,
444            BoxMakeHeaderValueFn::new(make_fn),
445            InsertHeaderMode::IfNotPresent,
446        )
447    }
448}
449
450impl<S, M> SetRequestHeader<S, M> {
451    /// Create a new [`SetRequestHeader`] from a [`Default`] [`MakeHeaderValue`].
452    ///
453    /// See [`SetRequestHeader::overriding`] for more details.
454    #[inline(always)]
455    pub fn overriding_default(
456        inner: S,
457        header_name: HeaderName,
458    ) -> SetRequestHeader<S, MakeHeaderValueDefault<M>> {
459        SetRequestHeader::new(
460            inner,
461            header_name,
462            MakeHeaderValueDefault::new(),
463            InsertHeaderMode::Override,
464        )
465    }
466
467    /// Create a new [`SetRequestHeader`] from a [`Default`] [`MakeHeaderValue`].
468    ///
469    /// See [`SetRequestHeader::appending`] for more details.
470    #[inline(always)]
471    pub fn appending_default(
472        inner: S,
473        header_name: HeaderName,
474    ) -> SetRequestHeader<S, MakeHeaderValueDefault<M>> {
475        SetRequestHeader::new(
476            inner,
477            header_name,
478            MakeHeaderValueDefault::new(),
479            InsertHeaderMode::Append,
480        )
481    }
482
483    /// Create a new [`SetRequestHeader`] from a [`Default`] [`MakeHeaderValue`].
484    ///
485    /// See [`SetRequestHeader::if_not_present`] for more details.
486    #[inline(always)]
487    pub fn if_not_present_default(
488        inner: S,
489        header_name: HeaderName,
490    ) -> SetRequestHeader<S, MakeHeaderValueDefault<M>> {
491        SetRequestHeader::new(
492            inner,
493            header_name,
494            MakeHeaderValueDefault::new(),
495            InsertHeaderMode::IfNotPresent,
496        )
497    }
498}
499
500impl<S, M: TypedHeader> SetRequestHeader<S, M> {
501    /// Create a new [`SetRequestHeader`] from a [`Default`] [`TypedHeader`].
502    ///
503    /// See [`SetRequestHeader::overriding`] for more details.
504    #[inline(always)]
505    pub fn overriding_default_typed(
506        inner: S,
507    ) -> SetRequestHeader<S, MakeHeaderValueDefault<TypedHeaderAsMaker<M>>> {
508        SetRequestHeader::new(
509            inner,
510            M::name().clone(),
511            MakeHeaderValueDefault::new(),
512            InsertHeaderMode::Override,
513        )
514    }
515
516    /// Create a new [`SetRequestHeader`] from a [`Default`] [`TypedHeader`].
517    ///
518    /// See [`SetRequestHeader::appending`] for more details.
519    #[inline(always)]
520    pub fn appending_default_typed(
521        inner: S,
522    ) -> SetRequestHeader<S, MakeHeaderValueDefault<TypedHeaderAsMaker<M>>> {
523        SetRequestHeader::new(
524            inner,
525            M::name().clone(),
526            MakeHeaderValueDefault::new(),
527            InsertHeaderMode::Append,
528        )
529    }
530
531    /// Create a new [`SetRequestHeader`] from a [`Default`] [`TypedHeader`].
532    ///
533    /// See [`SetRequestHeader::if_not_present`] for more details.
534    #[inline(always)]
535    pub fn if_not_present_default_typed(
536        inner: S,
537    ) -> SetRequestHeader<S, MakeHeaderValueDefault<TypedHeaderAsMaker<M>>> {
538        SetRequestHeader::new(
539            inner,
540            M::name().clone(),
541            MakeHeaderValueDefault::new(),
542            InsertHeaderMode::IfNotPresent,
543        )
544    }
545}
546
547impl<S, M> fmt::Debug for SetRequestHeader<S, M>
548where
549    S: fmt::Debug,
550{
551    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552        f.debug_struct("SetRequestHeader")
553            .field("inner", &self.inner)
554            .field("header_name", &self.header_name)
555            .field("mode", &self.mode)
556            .field("make", &std::any::type_name::<M>())
557            .finish()
558    }
559}
560
561impl<ReqBody, ResBody, S, M> Service<Request<ReqBody>> for SetRequestHeader<S, M>
562where
563    ReqBody: Send + 'static,
564    ResBody: Send + 'static,
565    S: Service<Request<ReqBody>, Output = Response<ResBody>>,
566    M: MakeHeaderValue<ReqBody>,
567{
568    type Output = S::Output;
569    type Error = S::Error;
570
571    async fn serve(&self, req: Request<ReqBody>) -> Result<Self::Output, Self::Error> {
572        let req = self.mode.apply(&self.header_name, req, &self.make).await;
573        self.inner.serve(req).await
574    }
575}