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}