aws_smithy_http_server/instrumentation/
mod.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6#![deny(missing_docs, missing_debug_implementations)]
7
8//! Provides [`InstrumentOperation`] and a variety of helpers structures for dealing with sensitive data. Together they
9//! allow compliance with the [sensitive trait].
10//!
11//! # Example
12//!
13//! ```
14//! # use std::convert::Infallible;
15//! # use aws_smithy_http_server::instrumentation::{*, sensitivity::{*, headers::*, uri::*}};
16//! # use aws_smithy_http_server::shape_id::ShapeId;
17//! # use http::{Request, Response};
18//! # use tower::{util::service_fn, Service};
19//! # async fn service(request: Request<()>) -> Result<Response<()>, Infallible> {
20//! #   Ok(Response::new(()))
21//! # }
22//! # async fn example() {
23//! # let service = service_fn(service);
24//! # const ID: ShapeId = ShapeId::new("namespace#foo-operation", "namespace", "foo-operation");
25//! let request = Request::get("http://localhost/a/b/c/d?bar=hidden")
26//!     .header("header-name-a", "hidden")
27//!     .body(())
28//!     .unwrap();
29//!
30//! let request_fmt = RequestFmt::new()
31//!     .header(|name| HeaderMarker {
32//!        value: name == "header-name-a",
33//!        key_suffix: None,
34//!     })
35//!     .query(|name| QueryMarker { key: false, value: name == "bar" })
36//!     .label(|index| index % 2 == 0, None);
37//! let response_fmt = ResponseFmt::new()
38//!     .header(|name| {
39//!         if name.as_str().starts_with("prefix-") {
40//!             HeaderMarker {
41//!                 value: true,
42//!                 key_suffix: Some("prefix-".len()),
43//!             }
44//!         } else {
45//!             HeaderMarker {
46//!                 value: name == "header-name-b",
47//!                 key_suffix: None,
48//!             }
49//!         }
50//!     })
51//!     .status_code();
52//! let mut service = InstrumentOperation::new(service, ID)
53//!     .request_fmt(request_fmt)
54//!     .response_fmt(response_fmt);
55//!
56//! let _ = service.call(request).await.unwrap();
57//! # }
58//! ```
59//!
60//! [sensitive trait]: https://smithy.io/2.0/spec/documentation-traits.html#sensitive-trait
61
62mod plugin;
63pub mod sensitivity;
64mod service;
65
66use std::fmt::{Debug, Display};
67
68pub use plugin::*;
69pub use service::*;
70
71/// A standard interface for taking some component of the HTTP request/response and transforming it into new struct
72/// which enjoys [`Debug`] or [`Display`]. This allows for polymorphism over formatting approaches.
73pub trait MakeFmt<T> {
74    /// Target of the `fmt` transformation.
75    type Target;
76
77    /// Transforms a source into a target, altering it's [`Display`] or [`Debug`] implementation.
78    fn make(&self, source: T) -> Self::Target;
79}
80
81impl<'a, T, U> MakeFmt<T> for &'a U
82where
83    U: MakeFmt<T>,
84{
85    type Target = U::Target;
86
87    fn make(&self, source: T) -> Self::Target {
88        U::make(self, source)
89    }
90}
91
92/// Identical to [`MakeFmt`] but with a [`Display`] bound on the associated type.
93pub trait MakeDisplay<T> {
94    /// Mirrors [`MakeFmt::Target`].
95    type Target: Display;
96
97    /// Mirrors [`MakeFmt::make`].
98    fn make_display(&self, source: T) -> Self::Target;
99}
100
101impl<T, U> MakeDisplay<T> for U
102where
103    U: MakeFmt<T>,
104    U::Target: Display,
105{
106    type Target = U::Target;
107
108    fn make_display(&self, source: T) -> Self::Target {
109        U::make(self, source)
110    }
111}
112
113/// Identical to [`MakeFmt`] but with a [`Debug`] bound on the associated type.
114pub trait MakeDebug<T> {
115    /// Mirrors [`MakeFmt::Target`].
116    type Target: Debug;
117
118    /// Mirrors [`MakeFmt::make`].
119    fn make_debug(&self, source: T) -> Self::Target;
120}
121
122impl<T, U> MakeDebug<T> for U
123where
124    U: MakeFmt<T>,
125    U::Target: Debug,
126{
127    type Target = U::Target;
128
129    fn make_debug(&self, source: T) -> Self::Target {
130        U::make(self, source)
131    }
132}
133
134/// A blanket, identity, [`MakeFmt`] implementation. Applies no changes to the [`Display`]/[`Debug`] implementation.
135#[derive(Debug, Clone, Default)]
136pub struct MakeIdentity;
137
138impl<T> MakeFmt<T> for MakeIdentity {
139    type Target = T;
140
141    fn make(&self, source: T) -> Self::Target {
142        source
143    }
144}