tower_http/set_header/request/mod.rs
1//! Middleware for setting headers on HTTP requests.
2//!
3//! This module provides middleware for setting one or more headers on HTTP requests, either with fixed values or values determined dynamically from the request.
4//!
5//! # Single Header
6//!
7//! Use [`SetRequestHeaderLayer`] and [`SetRequestHeader`] to set a single header. The header value can be a fixed value or computed dynamically using a closure. See [`crate::set_header::MakeHeaderValue`] for details.
8//!
9//! ## Example: Fixed Value
10//!
11//! ```
12//! use http::{Request, Response, header::{self, HeaderValue}};
13//! use tower::{Service, ServiceExt, ServiceBuilder};
14//! use tower_http::set_header::SetRequestHeaderLayer;
15//! use http_body_util::Full;
16//! use bytes::Bytes;
17//!
18//! # #[tokio::main]
19//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
20//! # let http_client = tower::service_fn(|_: Request<Full<Bytes>>| async move {
21//! # Ok::<_, std::convert::Infallible>(Response::new(Full::<Bytes>::default()))
22//! # });
23//! #
24//! let mut svc = ServiceBuilder::new()
25//! .layer(
26//! // Layer that sets `User-Agent: my very cool app` on requests.
27//! //
28//! // `if_not_present` will only insert the header if it does not already
29//! // have a value.
30//! SetRequestHeaderLayer::if_not_present(
31//! header::USER_AGENT,
32//! HeaderValue::from_static("my very cool app"),
33//! )
34//! )
35//! .service(http_client);
36//!
37//! let request = Request::new(Full::default());
38//!
39//! let response = svc.ready().await?.call(request).await?;
40//! #
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! Setting a header based on a value determined dynamically from the request:
46//!
47//! ```
48//! use http::{Request, Response, header::{self, HeaderValue}};
49//! use tower::{Service, ServiceExt, ServiceBuilder};
50//! use tower_http::set_header::SetRequestHeaderLayer;
51//! use bytes::Bytes;
52//! use http_body_util::Full;
53//!
54//! # #[tokio::main]
55//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
56//! # let http_client = tower::service_fn(|_: Request<Full<Bytes>>| async move {
57//! # Ok::<_, std::convert::Infallible>(Response::new(Full::<Bytes>::default()))
58//! # });
59//! fn date_header_value() -> HeaderValue {
60//! // ...
61//! # HeaderValue::from_static("now")
62//! }
63//!
64//! let mut svc = ServiceBuilder::new()
65//! .layer(
66//! // Layer that sets `Date` to the current date and time.
67//! //
68//! // `overriding` will insert the header and override any previous values it
69//! // may have.
70//! SetRequestHeaderLayer::overriding(
71//! header::DATE,
72//! |request: &Request<Full<Bytes>>| {
73//! Some(date_header_value())
74//! }
75//! )
76//! )
77//! .service(http_client);
78//!
79//! let request = Request::new(Full::default());
80//!
81//! let response = svc.ready().await?.call(request).await?;
82//! #
83//! # Ok(())
84//! # }
85//! ```
86//!
87//! # Multiple Headers
88//!
89//! Use [`SetMultipleRequestHeadersLayer`] and [`SetMultipleRequestHeader`] to set multiple headers at once. Each header can have a fixed value or be computed dynamically.
90//!
91//! Note: this layer uses boxing (allocation + dynamic dispatch) to support mixed producer
92//! types in a single `vec`. Stacking multiple [`SetRequestHeaderLayer`] instances avoids this at the
93//! cost of a more complex composed service type.
94//!
95//! ## Example: Multiple Dynamic Values
96//!
97//! ```
98//! use http::{Request, Response, header::{self, HeaderValue}};
99//! use tower::{Service, ServiceExt, ServiceBuilder};
100//! use tower_http::set_header::{HeaderMetadata, request::{SetMultipleRequestHeadersLayer}};
101//! use bytes::Bytes;
102//! use http_body_util::Full;
103//!
104//! # #[tokio::main]
105//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
106//! # let http_client = tower::service_fn(|_: Request<Full<Bytes>>| async move {
107//! # Ok::<_, std::convert::Infallible>(Response::new(Full::<Bytes>::default()))
108//! # });
109//!
110//! let mut svc = ServiceBuilder::new()
111//! .layer(
112//! SetMultipleRequestHeadersLayer::overriding(vec![
113//! (header::DATE, |_: &Request<Full<Bytes>>| {
114//! Some(HeaderValue::from_static("now"))
115//! }).into(),
116//! ])
117//! )
118//! .service(tower::service_fn(|req: Request<Full<Bytes>>| async move {
119//! assert_eq!(req.headers()["date"], "now");
120//! Ok::<_, std::convert::Infallible>(Response::new(Full::<Bytes>::default()))
121//! }));
122//!
123//! let request = Request::new(Full::default());
124//!
125//! let _response = svc.ready().await?.call(request).await?;
126//! # Ok(())
127//! # }
128//! ```
129//!
130//! # Modes
131//!
132//! - `overriding`: If a previous value exists for the same header, it is removed and replaced with the new value.
133//! - `appending`: The new header is always added, preserving any existing values. If previous values exist, the header will have multiple values.
134//! - `if_not_present`: If a previous value exists for the header, the new value is not inserted.
135//!
136//! See [`SetRequestHeaderLayer`], [`SetRequestHeader`], [`SetMultipleRequestHeadersLayer`], and [`SetMultipleRequestHeader`] for more details.
137
138mod multiple_headers;
139mod single_header;
140
141pub use multiple_headers::{SetMultipleRequestHeader, SetMultipleRequestHeadersLayer};
142pub use single_header::{SetRequestHeader, SetRequestHeaderLayer};