tower_http/set_header/
mod.rs1use std::fmt;
6
7use http::{header::HeaderName, HeaderMap, HeaderValue, Request, Response};
8
9pub mod request;
10pub mod response;
11
12#[doc(inline)]
13pub use self::{
14 request::{SetRequestHeader, SetRequestHeaderLayer},
15 response::{SetResponseHeader, SetResponseHeaderLayer},
16};
17
18pub trait MakeHeaderValue<T> {
28 fn make_header_value(&mut self, message: &T) -> Option<HeaderValue>;
30}
31
32impl<F, T> MakeHeaderValue<T> for F
33where
34 F: FnMut(&T) -> Option<HeaderValue>,
35{
36 fn make_header_value(&mut self, message: &T) -> Option<HeaderValue> {
37 self(message)
38 }
39}
40
41impl<T> MakeHeaderValue<T> for HeaderValue {
42 fn make_header_value(&mut self, _message: &T) -> Option<HeaderValue> {
43 Some(self.clone())
44 }
45}
46
47impl<T> MakeHeaderValue<T> for Option<HeaderValue> {
48 fn make_header_value(&mut self, _message: &T) -> Option<HeaderValue> {
49 self.clone()
50 }
51}
52
53#[derive(Debug, Clone, Copy)]
54enum InsertHeaderMode {
55 Override,
56 Append,
57 IfNotPresent,
58}
59
60impl InsertHeaderMode {
61 fn apply<T, M>(self, header_name: &HeaderName, target: &mut T, make: &mut M)
62 where
63 T: Headers,
64 M: MakeHeaderValue<T>,
65 {
66 match self {
67 InsertHeaderMode::Override => {
68 if let Some(value) = make.make_header_value(target) {
69 target.headers_mut().insert(header_name.clone(), value);
70 }
71 }
72 InsertHeaderMode::IfNotPresent => {
73 if !target.headers().contains_key(header_name) {
74 if let Some(value) = make.make_header_value(target) {
75 target.headers_mut().insert(header_name.clone(), value);
76 }
77 }
78 }
79 InsertHeaderMode::Append => {
80 if let Some(value) = make.make_header_value(target) {
81 target.headers_mut().append(header_name.clone(), value);
82 }
83 }
84 }
85 }
86}
87
88trait Headers {
89 fn headers(&self) -> &HeaderMap;
90
91 fn headers_mut(&mut self) -> &mut HeaderMap;
92}
93
94impl<B> Headers for Request<B> {
95 fn headers(&self) -> &HeaderMap {
96 Request::headers(self)
97 }
98
99 fn headers_mut(&mut self) -> &mut HeaderMap {
100 Request::headers_mut(self)
101 }
102}
103
104impl<B> Headers for Response<B> {
105 fn headers(&self) -> &HeaderMap {
106 Response::headers(self)
107 }
108
109 fn headers_mut(&mut self) -> &mut HeaderMap {
110 Response::headers_mut(self)
111 }
112}
113
114trait CloneableMakeHeaderValue<T>: MakeHeaderValue<T> + Send + Sync {
116 fn clone_box(&self) -> Box<dyn CloneableMakeHeaderValue<T>>;
117}
118
119impl<T, M> CloneableMakeHeaderValue<T> for M
120where
121 M: MakeHeaderValue<T> + Clone + Send + Sync + 'static,
122{
123 fn clone_box(&self) -> Box<dyn CloneableMakeHeaderValue<T>> {
124 Box::new(self.clone())
125 }
126}
127
128struct BoxedMakeHeaderValue<T>(Box<dyn CloneableMakeHeaderValue<T>>);
130
131impl<T> BoxedMakeHeaderValue<T> {
132 fn new<M>(maker: M) -> Self
134 where
135 M: MakeHeaderValue<T> + Clone + Send + Sync + 'static,
136 {
137 Self(Box::new(maker))
138 }
139}
140
141impl<T> Clone for BoxedMakeHeaderValue<T> {
142 fn clone(&self) -> Self {
143 Self(self.0.clone_box())
144 }
145}
146
147impl<T> MakeHeaderValue<T> for BoxedMakeHeaderValue<T> {
148 fn make_header_value(&mut self, message: &T) -> Option<HeaderValue> {
149 self.0.make_header_value(message)
150 }
151}
152
153impl<T> fmt::Debug for BoxedMakeHeaderValue<T> {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 f.debug_struct("BoxedMakeHeaderValue").finish()
156 }
157}
158
159#[derive(Clone, Debug)]
161pub struct HeaderMetadata<T> {
162 header_name: HeaderName,
164 make: BoxedMakeHeaderValue<T>,
166}
167
168impl<T> HeaderMetadata<T> {
169 fn new<M: MakeHeaderValue<T> + Clone + 'static + Send + Sync>(
171 header_name: HeaderName,
172 make: M,
173 ) -> Self {
174 Self {
175 header_name,
176 make: BoxedMakeHeaderValue::new(make),
177 }
178 }
179
180 fn build_config(self, mode: InsertHeaderMode) -> HeaderInsertionConfig<T> {
182 HeaderInsertionConfig {
183 header_name: self.header_name,
184 make: self.make,
185 mode,
186 }
187 }
188}
189
190impl<T, M> From<(HeaderName, M)> for HeaderMetadata<T>
191where
192 M: MakeHeaderValue<T> + Clone + 'static + Send + Sync,
193{
194 fn from((header_name, make): (HeaderName, M)) -> Self {
195 HeaderMetadata::new(header_name, make)
196 }
197}
198
199struct HeaderInsertionConfig<T> {
201 header_name: HeaderName,
202 make: BoxedMakeHeaderValue<T>,
203 mode: InsertHeaderMode,
204}
205
206impl<T> Clone for HeaderInsertionConfig<T>
207where
208 BoxedMakeHeaderValue<T>: Clone,
209{
210 fn clone(&self) -> Self {
211 Self {
212 header_name: self.header_name.clone(),
213 make: self.make.clone(),
214 mode: self.mode,
215 }
216 }
217}
218
219impl<T> fmt::Debug for HeaderInsertionConfig<T> {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 f.debug_struct("HeaderInsertionConfig")
222 .field("header_name", &self.header_name)
223 .field("mode", &self.mode)
224 .field("make", &"BoxedMakeHeaderValue")
225 .finish()
226 }
227}