aws_smithy_http_server/instrumentation/sensitivity/
request.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! A builder whose methods allow for configuration of [`MakeFmt`] implementations over parts of [`http::Request`].
7
8use std::fmt::{Debug, Error, Formatter};
9
10use http::{header::HeaderName, HeaderMap};
11
12use crate::instrumentation::{MakeFmt, MakeIdentity};
13
14use super::{
15    headers::{HeaderMarker, MakeHeaders},
16    uri::{GreedyLabel, MakeLabel, MakeQuery, MakeUri, QueryMarker},
17};
18
19/// Allows the modification the requests URIs [`Display`](std::fmt::Display) and headers
20/// [`Debug`] to accommodate sensitivity.
21///
22/// This enjoys [`MakeFmt`] for [`&HeaderMap`](HeaderMap) and [`&Uri`](http::Uri).
23#[derive(Clone)]
24pub struct RequestFmt<Headers, Uri> {
25    headers: Headers,
26    uri: Uri,
27}
28
29impl<Headers, Uri> Debug for RequestFmt<Headers, Uri> {
30    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
31        f.debug_struct("RequestFmt").finish_non_exhaustive()
32    }
33}
34
35/// Default [`RequestFmt`].
36pub type DefaultRequestFmt = RequestFmt<MakeIdentity, MakeUri<MakeIdentity, MakeIdentity>>;
37
38impl Default for DefaultRequestFmt {
39    fn default() -> Self {
40        Self {
41            headers: MakeIdentity,
42            uri: MakeUri::default(),
43        }
44    }
45}
46
47impl DefaultRequestFmt {
48    /// Constructs a new [`RequestFmt`] with no redactions.
49    pub fn new() -> Self {
50        Self::default()
51    }
52}
53
54impl<Header, Uri> RequestFmt<Header, Uri> {
55    /// Marks parts of headers as sensitive using a closure.
56    ///
57    /// See [`SensitiveHeaders`](super::headers::SensitiveHeaders) for more info.
58    pub fn header<F>(self, headers: F) -> RequestFmt<MakeHeaders<F>, Uri>
59    where
60        F: Fn(&HeaderName) -> HeaderMarker,
61    {
62        RequestFmt {
63            headers: MakeHeaders(headers),
64            uri: self.uri,
65        }
66    }
67}
68
69impl<Header, P, Q> RequestFmt<Header, MakeUri<P, Q>> {
70    /// Marks parts of the URI as sensitive.
71    ///
72    /// See [`Label`](super::uri::Label) for more info.
73    pub fn label<F>(
74        self,
75        label_marker: F,
76        greedy_label: Option<GreedyLabel>,
77    ) -> RequestFmt<Header, MakeUri<MakeLabel<F>, Q>>
78    where
79        F: Fn(usize) -> bool,
80    {
81        RequestFmt {
82            headers: self.headers,
83            uri: MakeUri {
84                make_path: MakeLabel {
85                    label_marker,
86                    greedy_label,
87                },
88                make_query: self.uri.make_query,
89            },
90        }
91    }
92
93    /// Marks parts of the query as sensitive.
94    ///
95    /// See [`Query`](super::uri::Query) for more info.
96    pub fn query<F>(self, query: F) -> RequestFmt<Header, MakeUri<P, MakeQuery<F>>>
97    where
98        F: Fn(&str) -> QueryMarker,
99    {
100        RequestFmt {
101            headers: self.headers,
102            uri: MakeUri {
103                make_path: self.uri.make_path,
104                make_query: MakeQuery(query),
105            },
106        }
107    }
108}
109
110impl<'a, Headers, Uri> MakeFmt<&'a HeaderMap> for RequestFmt<Headers, Uri>
111where
112    Headers: MakeFmt<&'a HeaderMap>,
113{
114    type Target = Headers::Target;
115
116    fn make(&self, source: &'a HeaderMap) -> Self::Target {
117        self.headers.make(source)
118    }
119}
120
121impl<'a, Headers, Uri> MakeFmt<&'a http::Uri> for RequestFmt<Headers, Uri>
122where
123    Uri: MakeFmt<&'a http::Uri>,
124{
125    type Target = Uri::Target;
126
127    fn make(&self, source: &'a http::Uri) -> Self::Target {
128        self.uri.make(source)
129    }
130}