tower_async_http/
sensitive_headers.rs1use http::{header::HeaderName, Request, Response};
42use std::sync::Arc;
43use tower_async_layer::Layer;
44use tower_async_service::Service;
45
46#[derive(Clone, Debug)]
54pub struct SetSensitiveHeadersLayer {
55 headers: Arc<[HeaderName]>,
56}
57
58impl SetSensitiveHeadersLayer {
59 pub fn new<I>(headers: I) -> Self
61 where
62 I: IntoIterator<Item = HeaderName>,
63 {
64 let headers = headers.into_iter().collect::<Vec<_>>();
65 Self::from_shared(headers.into())
66 }
67
68 pub fn from_shared(headers: Arc<[HeaderName]>) -> Self {
70 Self { headers }
71 }
72}
73
74impl<S> Layer<S> for SetSensitiveHeadersLayer {
75 type Service = SetSensitiveHeaders<S>;
76
77 fn layer(&self, inner: S) -> Self::Service {
78 SetSensitiveRequestHeaders::from_shared(
79 SetSensitiveResponseHeaders::from_shared(inner, self.headers.clone()),
80 self.headers.clone(),
81 )
82 }
83}
84
85pub type SetSensitiveHeaders<S> = SetSensitiveRequestHeaders<SetSensitiveResponseHeaders<S>>;
91
92#[derive(Clone, Debug)]
100pub struct SetSensitiveRequestHeadersLayer {
101 headers: Arc<[HeaderName]>,
102}
103
104impl SetSensitiveRequestHeadersLayer {
105 pub fn new<I>(headers: I) -> Self
107 where
108 I: IntoIterator<Item = HeaderName>,
109 {
110 let headers = headers.into_iter().collect::<Vec<_>>();
111 Self::from_shared(headers.into())
112 }
113
114 pub fn from_shared(headers: Arc<[HeaderName]>) -> Self {
116 Self { headers }
117 }
118}
119
120impl<S> Layer<S> for SetSensitiveRequestHeadersLayer {
121 type Service = SetSensitiveRequestHeaders<S>;
122
123 fn layer(&self, inner: S) -> Self::Service {
124 SetSensitiveRequestHeaders {
125 inner,
126 headers: self.headers.clone(),
127 }
128 }
129}
130
131#[derive(Clone, Debug)]
137pub struct SetSensitiveRequestHeaders<S> {
138 inner: S,
139 headers: Arc<[HeaderName]>,
140}
141
142impl<S> SetSensitiveRequestHeaders<S> {
143 pub fn new<I>(inner: S, headers: I) -> Self
145 where
146 I: IntoIterator<Item = HeaderName>,
147 {
148 let headers = headers.into_iter().collect::<Vec<_>>();
149 Self::from_shared(inner, headers.into())
150 }
151
152 pub fn from_shared(inner: S, headers: Arc<[HeaderName]>) -> Self {
154 Self { inner, headers }
155 }
156
157 define_inner_service_accessors!();
158
159 pub fn layer<I>(headers: I) -> SetSensitiveRequestHeadersLayer
163 where
164 I: IntoIterator<Item = HeaderName>,
165 {
166 SetSensitiveRequestHeadersLayer::new(headers)
167 }
168}
169
170impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for SetSensitiveRequestHeaders<S>
171where
172 S: Service<Request<ReqBody>, Response = Response<ResBody>>,
173{
174 type Response = S::Response;
175 type Error = S::Error;
176
177 async fn call(&self, mut req: Request<ReqBody>) -> Result<Self::Response, Self::Error> {
178 let headers = req.headers_mut();
179 for header in &*self.headers {
180 if let http::header::Entry::Occupied(mut entry) = headers.entry(header) {
181 for value in entry.iter_mut() {
182 value.set_sensitive(true);
183 }
184 }
185 }
186
187 self.inner.call(req).await
188 }
189}
190
191#[derive(Clone, Debug)]
199pub struct SetSensitiveResponseHeadersLayer {
200 headers: Arc<[HeaderName]>,
201}
202
203impl SetSensitiveResponseHeadersLayer {
204 pub fn new<I>(headers: I) -> Self
206 where
207 I: IntoIterator<Item = HeaderName>,
208 {
209 let headers = headers.into_iter().collect::<Vec<_>>();
210 Self::from_shared(headers.into())
211 }
212
213 pub fn from_shared(headers: Arc<[HeaderName]>) -> Self {
215 Self { headers }
216 }
217}
218
219impl<S> Layer<S> for SetSensitiveResponseHeadersLayer {
220 type Service = SetSensitiveResponseHeaders<S>;
221
222 fn layer(&self, inner: S) -> Self::Service {
223 SetSensitiveResponseHeaders {
224 inner,
225 headers: self.headers.clone(),
226 }
227 }
228}
229
230#[derive(Clone, Debug)]
236pub struct SetSensitiveResponseHeaders<S> {
237 inner: S,
238 headers: Arc<[HeaderName]>,
239}
240
241impl<S> SetSensitiveResponseHeaders<S> {
242 pub fn new<I>(inner: S, headers: I) -> Self
244 where
245 I: IntoIterator<Item = HeaderName>,
246 {
247 let headers = headers.into_iter().collect::<Vec<_>>();
248 Self::from_shared(inner, headers.into())
249 }
250
251 pub fn from_shared(inner: S, headers: Arc<[HeaderName]>) -> Self {
253 Self { inner, headers }
254 }
255
256 define_inner_service_accessors!();
257
258 pub fn layer<I>(headers: I) -> SetSensitiveResponseHeadersLayer
262 where
263 I: IntoIterator<Item = HeaderName>,
264 {
265 SetSensitiveResponseHeadersLayer::new(headers)
266 }
267}
268
269impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for SetSensitiveResponseHeaders<S>
270where
271 S: Service<Request<ReqBody>, Response = Response<ResBody>>,
272{
273 type Response = S::Response;
274 type Error = S::Error;
275
276 async fn call(&self, req: Request<ReqBody>) -> Result<Self::Response, Self::Error> {
277 let mut res = self.inner.call(req).await?;
278
279 let headers = res.headers_mut();
280 for header in self.headers.iter() {
281 if let http::header::Entry::Occupied(mut entry) = headers.entry(header) {
282 for value in entry.iter_mut() {
283 value.set_sensitive(true);
284 }
285 }
286 }
287
288 Ok(res)
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 #[allow(unused_imports)]
295 use super::*;
296 use http::header;
297 use tower_async::ServiceBuilder;
298
299 #[tokio::test]
300 async fn multiple_value_header() {
301 async fn response_set_cookie(req: http::Request<()>) -> Result<http::Response<()>, ()> {
302 let mut iter = req.headers().get_all(header::COOKIE).iter().peekable();
303
304 assert!(iter.peek().is_some());
305
306 for value in iter {
307 assert!(value.is_sensitive())
308 }
309
310 let mut resp = http::Response::new(());
311 resp.headers_mut().append(
312 header::CONTENT_TYPE,
313 http::HeaderValue::from_static("text/html"),
314 );
315 resp.headers_mut().append(
316 header::SET_COOKIE,
317 http::HeaderValue::from_static("cookie-1"),
318 );
319 resp.headers_mut().append(
320 header::SET_COOKIE,
321 http::HeaderValue::from_static("cookie-2"),
322 );
323 resp.headers_mut().append(
324 header::SET_COOKIE,
325 http::HeaderValue::from_static("cookie-3"),
326 );
327 Ok(resp)
328 }
329
330 let service = ServiceBuilder::new()
331 .layer(SetSensitiveRequestHeadersLayer::new(vec![header::COOKIE]))
332 .layer(SetSensitiveResponseHeadersLayer::new(vec![
333 header::SET_COOKIE,
334 ]))
335 .service_fn(response_set_cookie);
336
337 let mut req = http::Request::new(());
338 req.headers_mut()
339 .append(header::COOKIE, http::HeaderValue::from_static("cookie+1"));
340 req.headers_mut()
341 .append(header::COOKIE, http::HeaderValue::from_static("cookie+2"));
342
343 let resp = service.call(req).await.unwrap();
344
345 assert!(!resp
346 .headers()
347 .get(header::CONTENT_TYPE)
348 .unwrap()
349 .is_sensitive());
350
351 let mut iter = resp.headers().get_all(header::SET_COOKIE).iter().peekable();
352
353 assert!(iter.peek().is_some());
354
355 for value in iter {
356 assert!(value.is_sensitive())
357 }
358 }
359}