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::{Context, Service, Layer};
16//! use rama_core::error::BoxError;
17//!
18//! # #[tokio::main]
19//! # async fn main() -> Result<(), BoxError> {
20//! # let http_client = service_fn(|_: Request| async move {
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//! ).layer(http_client);
34//!
35//! let request = Request::new(Body::empty());
36//!
37//! let response = svc.serve(Context::default(), 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::{Context, 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 move {
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 move {
70//! Some(date_header_value())
71//! }
72//! ),
73//! ).layer(http_client);
74//!
75//! let request = Request::new(Body::default());
76//!
77//! let response = svc.serve(Context::default(), request).await?;
78//! #
79//! # Ok(())
80//! # }
81//! ```
82
83use crate::{
84 header::HeaderName,
85 headers::{Header, HeaderExt},
86 HeaderValue, Request, Response,
87};
88use rama_core::{Context, Layer, Service};
89use rama_utils::macros::define_inner_service_accessors;
90use std::fmt;
91
92mod header;
93use header::InsertHeaderMode;
94
95pub use header::{BoxMakeHeaderValueFn, MakeHeaderValue};
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 pub fn overriding(header_name: HeaderName, make: M) -> Self {
122 Self::new(header_name, make, InsertHeaderMode::Override)
123 }
124
125 /// Create a new [`SetRequestHeaderLayer`].
126 ///
127 /// The new header is always added, preserving any existing values. If previous values exist,
128 /// the header will have multiple values.
129 pub fn appending(header_name: HeaderName, make: M) -> Self {
130 Self::new(header_name, make, InsertHeaderMode::Append)
131 }
132
133 /// Create a new [`SetRequestHeaderLayer`].
134 ///
135 /// If a previous value exists for the header, the new value is not inserted.
136 pub fn if_not_present(header_name: HeaderName, make: M) -> Self {
137 Self::new(header_name, make, InsertHeaderMode::IfNotPresent)
138 }
139
140 fn new(header_name: HeaderName, make: M, mode: InsertHeaderMode) -> Self {
141 Self {
142 make,
143 header_name,
144 mode,
145 }
146 }
147}
148
149impl SetRequestHeaderLayer<HeaderValue> {
150 /// Create a new [`SetRequestHeaderLayer`] from a typed [`Header`].
151 ///
152 /// See [`SetRequestHeaderLayer::overriding`] for more details.
153 pub fn overriding_typed<H: Header>(header: H) -> Self {
154 Self::overriding(H::name().clone(), header.encode_to_value())
155 }
156
157 /// Create a new [`SetRequestHeaderLayer`] from a typed [`Header`].
158 ///
159 /// See [`SetRequestHeaderLayer::appending`] for more details.
160 pub fn appending_typed<H: Header>(header: H) -> Self {
161 Self::appending(H::name().clone(), header.encode_to_value())
162 }
163
164 /// Create a new [`SetRequestHeaderLayer`] from a typed [`Header`].
165 ///
166 /// See [`SetRequestHeaderLayer::if_not_present`] for more details.
167 pub fn if_not_present_typed<H: Header>(header: H) -> Self {
168 Self::if_not_present(H::name().clone(), header.encode_to_value())
169 }
170}
171
172impl<F, A> SetRequestHeaderLayer<BoxMakeHeaderValueFn<F, A>> {
173 /// Create a new [`SetRequestHeaderLayer`] from a [`super::MakeHeaderValueFn`].
174 ///
175 /// See [`SetRequestHeaderLayer::overriding`] for more details.
176 pub fn overriding_fn(header_name: HeaderName, make_fn: F) -> Self {
177 Self::new(
178 header_name,
179 BoxMakeHeaderValueFn::new(make_fn),
180 InsertHeaderMode::Override,
181 )
182 }
183
184 /// Create a new [`SetRequestHeaderLayer`] from a [`super::MakeHeaderValueFn`].
185 ///
186 /// See [`SetRequestHeaderLayer::appending`] for more details.
187 pub fn appending_fn(header_name: HeaderName, make_fn: F) -> Self {
188 Self::new(
189 header_name,
190 BoxMakeHeaderValueFn::new(make_fn),
191 InsertHeaderMode::Append,
192 )
193 }
194
195 /// Create a new [`SetRequestHeaderLayer`] from a [`super::MakeHeaderValueFn`].
196 ///
197 /// See [`SetRequestHeaderLayer::if_not_present`] for more details.
198 pub fn if_not_present_fn(header_name: HeaderName, make_fn: F) -> Self {
199 Self::new(
200 header_name,
201 BoxMakeHeaderValueFn::new(make_fn),
202 InsertHeaderMode::IfNotPresent,
203 )
204 }
205}
206
207impl<S, M> Layer<S> for SetRequestHeaderLayer<M>
208where
209 M: Clone,
210{
211 type Service = SetRequestHeader<S, M>;
212
213 fn layer(&self, inner: S) -> Self::Service {
214 SetRequestHeader {
215 inner,
216 header_name: self.header_name.clone(),
217 make: self.make.clone(),
218 mode: self.mode,
219 }
220 }
221}
222
223impl<M> Clone for SetRequestHeaderLayer<M>
224where
225 M: Clone,
226{
227 fn clone(&self) -> Self {
228 Self {
229 make: self.make.clone(),
230 header_name: self.header_name.clone(),
231 mode: self.mode,
232 }
233 }
234}
235
236/// Middleware that sets a header on the request.
237#[derive(Clone)]
238pub struct SetRequestHeader<S, M> {
239 inner: S,
240 header_name: HeaderName,
241 make: M,
242 mode: InsertHeaderMode,
243}
244
245impl<S, M> SetRequestHeader<S, M> {
246 /// Create a new [`SetRequestHeader`].
247 ///
248 /// If a previous value exists for the same header, it is removed and replaced with the new
249 /// header value.
250 pub fn overriding(inner: S, header_name: HeaderName, make: M) -> Self {
251 Self::new(inner, header_name, make, InsertHeaderMode::Override)
252 }
253
254 /// Create a new [`SetRequestHeader`].
255 ///
256 /// The new header is always added, preserving any existing values. If previous values exist,
257 /// the header will have multiple values.
258 pub fn appending(inner: S, header_name: HeaderName, make: M) -> Self {
259 Self::new(inner, header_name, make, InsertHeaderMode::Append)
260 }
261
262 /// Create a new [`SetRequestHeader`].
263 ///
264 /// If a previous value exists for the header, the new value is not inserted.
265 pub fn if_not_present(inner: S, header_name: HeaderName, make: M) -> Self {
266 Self::new(inner, header_name, make, InsertHeaderMode::IfNotPresent)
267 }
268
269 fn new(inner: S, header_name: HeaderName, make: M, mode: InsertHeaderMode) -> Self {
270 Self {
271 inner,
272 header_name,
273 make,
274 mode,
275 }
276 }
277
278 define_inner_service_accessors!();
279}
280
281impl<S, F, A> SetRequestHeader<S, BoxMakeHeaderValueFn<F, A>> {
282 /// Create a new [`SetRequestHeader`] from a [`super::MakeHeaderValueFn`].
283 ///
284 /// See [`SetRequestHeader::overriding`] for more details.
285 pub fn overriding_fn(inner: S, header_name: HeaderName, make_fn: F) -> Self {
286 Self::new(
287 inner,
288 header_name,
289 BoxMakeHeaderValueFn::new(make_fn),
290 InsertHeaderMode::Override,
291 )
292 }
293
294 /// Create a new [`SetRequestHeader`] from a [`super::MakeHeaderValueFn`].
295 ///
296 /// See [`SetRequestHeader::appending`] for more details.
297 pub fn appending_fn(inner: S, header_name: HeaderName, make_fn: F) -> Self {
298 Self::new(
299 inner,
300 header_name,
301 BoxMakeHeaderValueFn::new(make_fn),
302 InsertHeaderMode::Append,
303 )
304 }
305
306 /// Create a new [`SetRequestHeader`] from a [`super::MakeHeaderValueFn`].
307 ///
308 /// See [`SetRequestHeader::if_not_present`] for more details.
309 pub fn if_not_present_fn(inner: S, header_name: HeaderName, make_fn: F) -> Self {
310 Self::new(
311 inner,
312 header_name,
313 BoxMakeHeaderValueFn::new(make_fn),
314 InsertHeaderMode::IfNotPresent,
315 )
316 }
317}
318
319impl<S, M> fmt::Debug for SetRequestHeader<S, M>
320where
321 S: fmt::Debug,
322{
323 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
324 f.debug_struct("SetRequestHeader")
325 .field("inner", &self.inner)
326 .field("header_name", &self.header_name)
327 .field("mode", &self.mode)
328 .field("make", &std::any::type_name::<M>())
329 .finish()
330 }
331}
332
333impl<ReqBody, ResBody, State, S, M> Service<State, Request<ReqBody>> for SetRequestHeader<S, M>
334where
335 ReqBody: Send + 'static,
336 ResBody: Send + 'static,
337 State: Clone + Send + Sync + 'static,
338 S: Service<State, Request<ReqBody>, Response = Response<ResBody>>,
339 M: MakeHeaderValue<State, ReqBody>,
340{
341 type Response = S::Response;
342 type Error = S::Error;
343
344 async fn serve(
345 &self,
346 ctx: Context<State>,
347 req: Request<ReqBody>,
348 ) -> Result<Self::Response, Self::Error> {
349 let (ctx, req) = self
350 .mode
351 .apply(&self.header_name, ctx, req, &self.make)
352 .await;
353 self.inner.serve(ctx, req).await
354 }
355}