From ecbaddd7d9fc4dc8e76f5e0bf595517b870f1398 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 2 Dec 2022 18:29:04 +0100 Subject: [PATCH 01/18] Request IDs Signed-off-by: Daniele Ahmed --- design/src/rfcs/rfc0024_request_id.md | 2 +- .../aws-smithy-http-server/Cargo.toml | 1 + .../aws-smithy-http-server/src/request/mod.rs | 1 + .../src/request/request_id.rs | 187 ++++++++++++++++++ 4 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 rust-runtime/aws-smithy-http-server/src/request/request_id.rs diff --git a/design/src/rfcs/rfc0024_request_id.md b/design/src/rfcs/rfc0024_request_id.md index 5c150ca200..14d16360f5 100644 --- a/design/src/rfcs/rfc0024_request_id.md +++ b/design/src/rfcs/rfc0024_request_id.md @@ -85,7 +85,7 @@ where } fn call(&mut self, mut req: http::Request) -> Self::Future { - request.extensions_mut().insert(ServerRequestId::new()); + req.extensions_mut().insert(ServerRequestId::new()); self.inner.call(req) } } diff --git a/rust-runtime/aws-smithy-http-server/Cargo.toml b/rust-runtime/aws-smithy-http-server/Cargo.toml index d3f7b47d97..7a1d6e81fe 100644 --- a/rust-runtime/aws-smithy-http-server/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server/Cargo.toml @@ -41,6 +41,7 @@ tracing = "0.1.35" tokio = { version = "1.8.4", features = ["full"] } tower = { version = "0.4.11", features = ["util", "make"], default-features = false } tower-http = { version = "0.3", features = ["add-extension", "map-response-body"] } +uuid = { version = "1", features = ["v4", "fast-rng", "macro-diagnostics"] } [dev-dependencies] pretty_assertions = "1" diff --git a/rust-runtime/aws-smithy-http-server/src/request/mod.rs b/rust-runtime/aws-smithy-http-server/src/request/mod.rs index 77369b871b..20e25743dd 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/mod.rs @@ -59,6 +59,7 @@ pub mod extension; #[cfg(feature = "aws-lambda")] #[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))] pub mod lambda; +pub mod request_id; fn internal_server_error() -> http::Response { let mut response = http::Response::new(empty()); diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs new file mode 100644 index 0000000000..6a73517f22 --- /dev/null +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -0,0 +1,187 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Request IDs +//! +//! Request IDs are of two kinds: +//! +//! * Client Request ID: the request ID sent from a client in the request header +//! * Server Request ID: the unique ID generated server-side for this request +//! +//! Both can be used at the same time and can be used as inputs in your operation handlers. +//! To use [`ClientRequestId`], specify which headers +//! may contain the client request ID. + +use std::{ + fmt::Display, + task::{Context, Poll}, +}; + +use http::request::Parts; +use thiserror::Error; +use tower::{Layer, Service}; +use uuid::Uuid; + +use crate::{body::BoxBody, response::IntoResponse}; + +use super::{internal_server_error, FromParts}; + +/// Opaque type for Server Request IDs. +/// +/// If it is missing, the request will be rejected with a `500 Internal Server Error` response. +#[derive(Clone, Debug)] +pub struct ServerRequestId { + id: Uuid, +} + +/// The server request ID has not been added to the [`Request`](http::Request) or has been previously removed. +#[non_exhaustive] +#[derive(Debug, Error)] +#[error("the `ServerRequestId` is not present in the `http::Request`")] +pub struct MissingServerRequestId; + +impl ServerRequestId { + pub fn new() -> Self { + Self { id: Uuid::new_v4() } + } +} + +impl Display for ServerRequestId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.id) + } +} + +impl

FromParts

for ServerRequestId { + type Rejection = MissingServerRequestId; + + fn from_parts(parts: &mut Parts) -> Result { + parts.extensions.remove().ok_or(MissingServerRequestId) + } +} +pub struct ServerRequestIdProvider { + inner: S, +} + +pub struct ServerRequestIdProviderLayer {} + +impl Layer for ServerRequestIdProviderLayer { + type Service = ServerRequestIdProvider; + + fn layer(&self, inner: S) -> Self::Service { + ServerRequestIdProvider { inner } + } +} + +impl Service> for ServerRequestIdProvider +where + S: Service>, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, mut req: http::Request) -> Self::Future { + req.extensions_mut().insert(ServerRequestId::new()); + self.inner.call(req) + } +} + +impl IntoResponse for MissingServerRequestId { + fn into_response(self) -> http::Response { + internal_server_error() + } +} + +/// The Client Request ID. +/// +/// If it is missing, the request will be rejected with a `500 Internal Server Error` response. +#[derive(Clone, Debug)] +pub struct ClientRequestId { + id: Box, +} + +/// The client request ID has not been added to the [`Request`](http::Request) or has been previously removed. +#[non_exhaustive] +#[derive(Debug, Error)] +#[error("the `ClientRequestId` is not present in the `http::Request`")] +pub struct MissingClientRequestId; + +impl ClientRequestId { + pub fn new(id: Box) -> Self { + Self { id } + } +} + +impl Display for ClientRequestId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.id) + } +} + +impl

FromParts

for Option { + type Rejection = MissingClientRequestId; + + fn from_parts(parts: &mut Parts) -> Result { + parts.extensions.remove::().ok_or(MissingClientRequestId) + } +} + +pub struct ClientRequestIdProvider<'a, S> { + inner: S, + possible_headers: &'a [&'static str], +} + +pub struct ClientRequestIdProviderLayer<'a> { + possible_headers: &'a [&'static str], +} + +impl<'a, S> Layer for ClientRequestIdProviderLayer<'a> { + type Service = ClientRequestIdProvider<'a, S>; + + fn layer(&self, inner: S) -> Self::Service { + ClientRequestIdProvider { + inner, + possible_headers: self.possible_headers, + } + } +} + +impl<'a, R, S> Service> for ClientRequestIdProvider<'a, S> +where + S: Service>, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, mut req: http::Request) -> Self::Future { + let mut id: Option = None; + for possible_header in self.possible_headers { + if let Some(value) = req.headers().get(*possible_header) { + if let Ok(value) = value.to_str() { + id = Some(ClientRequestId::new(value.into())); + break; + } + } + } + req.extensions_mut().insert(id); + self.inner.call(req) + } +} + +impl IntoResponse for MissingClientRequestId { + fn into_response(self) -> http::Response { + internal_server_error() + } +} From 9f35197ffb85ad8693278ee78c66fb0c930350ba Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 2 Dec 2022 18:59:57 +0100 Subject: [PATCH 02/18] Add example Signed-off-by: Daniele Ahmed --- .../src/bin/pokemon-service-connect-info.rs | 30 +++++++++++++++---- .../src/request/request_id.rs | 18 +++++++++-- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index 8d17756ff1..db077b1952 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -5,14 +5,19 @@ use std::net::{IpAddr, SocketAddr}; -use aws_smithy_http_server::request::connect_info::ConnectInfo; -use clap::Parser; -use pokemon_service::{ - capture_pokemon, check_health, do_nothing, get_pokemon_species, get_server_statistics, setup_tracing, +use aws_smithy_http_server::request::request_id::ClientRequestIdProviderLayer; +use aws_smithy_http_server::request::request_id::ServerRequestIdProviderLayer; +use aws_smithy_http_server::{ + request::connect_info::ConnectInfo, request::request_id::ClientRequestId, request::request_id::ServerRequestId, + Extension, }; +use clap::Parser; +use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; use pokemon_service_server_sdk::{ error::{GetStorageError, NotAuthorized}, + input::DoNothingInput, input::GetStorageInput, + output::DoNothingOutput, output::GetStorageOutput, PokemonService, }; @@ -55,6 +60,18 @@ pub async fn get_storage_with_local_approved( Err(GetStorageError::NotAuthorized(NotAuthorized {})) } +pub async fn do_nothing_but_log_request_ids( + _input: DoNothingInput, + server_request_id: Extension, + client_request_id: Extension>, +) -> DoNothingOutput { + println!( + "This request has this client ID: {:?} and server ID: {}", + client_request_id.0, server_request_id.0 + ); + DoNothingOutput {} +} + #[tokio::main] async fn main() { let args = Args::parse(); @@ -64,11 +81,14 @@ async fn main() { .get_storage(get_storage_with_local_approved) .get_server_statistics(get_server_statistics) .capture_pokemon(capture_pokemon) - .do_nothing(do_nothing) + .do_nothing(do_nothing_but_log_request_ids) .check_health(check_health) .build() .expect("failed to build an instance of PokemonService"); + let app = app.layer(&ServerRequestIdProviderLayer::new()); + let app = app.layer(&ClientRequestIdProviderLayer::new(&["x-request-id"])); + // Start the [`hyper::Server`]. let bind: std::net::SocketAddr = format!("{}:{}", args.address, args.port) .parse() diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index 6a73517f22..9de0c801a3 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -61,12 +61,19 @@ impl

FromParts

for ServerRequestId { parts.extensions.remove().ok_or(MissingServerRequestId) } } +#[derive(Clone)] pub struct ServerRequestIdProvider { inner: S, } pub struct ServerRequestIdProviderLayer {} +impl ServerRequestIdProviderLayer { + pub fn new() -> Self { + Self {} + } +} + impl Layer for ServerRequestIdProviderLayer { type Service = ServerRequestIdProvider; @@ -133,13 +140,20 @@ impl

FromParts

for Option { } } +#[derive(Clone)] pub struct ClientRequestIdProvider<'a, S> { inner: S, - possible_headers: &'a [&'static str], + possible_headers: &'a [&'a str], } pub struct ClientRequestIdProviderLayer<'a> { - possible_headers: &'a [&'static str], + possible_headers: &'a [&'a str], +} + +impl<'a> ClientRequestIdProviderLayer<'a> { + pub fn new(possible_headers: &'a [&'a str]) -> Self { + Self { possible_headers } + } } impl<'a, S> Layer for ClientRequestIdProviderLayer<'a> { From f058767ca8f749b9f36c26c0c71fc84824af5827 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 2 Dec 2022 19:01:27 +0100 Subject: [PATCH 03/18] RFC status: implemented Signed-off-by: Daniele Ahmed --- design/src/rfcs/rfc0024_request_id.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/design/src/rfcs/rfc0024_request_id.md b/design/src/rfcs/rfc0024_request_id.md index 14d16360f5..542e407f15 100644 --- a/design/src/rfcs/rfc0024_request_id.md +++ b/design/src/rfcs/rfc0024_request_id.md @@ -1,7 +1,7 @@ RFC: RequestID in business logic handlers ============= -> Status: RFC +> Status: Implemented > > Applies to: server @@ -131,7 +131,7 @@ Although the generated ID is opaque, this will give guarantees to customers as t Changes checklist ----------------- -- [ ] Implement `ServerRequestId`: a `new()` function that generates a UUID, with `Display`, `Debug` and `ToStr` implementations -- [ ] Implement `ClientRequestId`: `new()` that wraps a string (the header value) and the header in which the value could be found, with `Display`, `Debug` and `ToStr` implementations +- [x] Implement `ServerRequestId`: a `new()` function that generates a UUID, with `Display`, `Debug` and `ToStr` implementations +- [x] Implement `ClientRequestId`: `new()` that wraps a string (the header value) and the header in which the value could be found, with `Display`, `Debug` and `ToStr` implementations - [x] Implement `FromParts` for `Extension` - [x] Implement `FromParts` for `Extension` From fabbaa2d5644338f3299bfa51bdf828e8d826151 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 2 Dec 2022 19:03:15 +0100 Subject: [PATCH 04/18] Clean imports Signed-off-by: Daniele Ahmed --- .../src/bin/pokemon-service-connect-info.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index db077b1952..e12eb7b247 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -5,20 +5,17 @@ use std::net::{IpAddr, SocketAddr}; -use aws_smithy_http_server::request::request_id::ClientRequestIdProviderLayer; -use aws_smithy_http_server::request::request_id::ServerRequestIdProviderLayer; use aws_smithy_http_server::{ - request::connect_info::ConnectInfo, request::request_id::ClientRequestId, request::request_id::ServerRequestId, - Extension, + request::connect_info::ConnectInfo, request::request_id::ClientRequestId, + request::request_id::ClientRequestIdProviderLayer, request::request_id::ServerRequestId, + request::request_id::ServerRequestIdProviderLayer, Extension, }; use clap::Parser; use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; use pokemon_service_server_sdk::{ error::{GetStorageError, NotAuthorized}, - input::DoNothingInput, - input::GetStorageInput, - output::DoNothingOutput, - output::GetStorageOutput, + input::{DoNothingInput, GetStorageInput}, + output::{DoNothingOutput, GetStorageOutput}, PokemonService, }; From b65062cc1b93405d024164d6bb70fecde5b760f9 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 2 Dec 2022 19:04:10 +0100 Subject: [PATCH 05/18] Use tracing Signed-off-by: Daniele Ahmed --- .../pokemon-service/src/bin/pokemon-service-connect-info.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index e12eb7b247..e4502f63c7 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -62,9 +62,10 @@ pub async fn do_nothing_but_log_request_ids( server_request_id: Extension, client_request_id: Extension>, ) -> DoNothingOutput { - println!( + tracing::debug!( "This request has this client ID: {:?} and server ID: {}", - client_request_id.0, server_request_id.0 + client_request_id.0, + server_request_id.0 ); DoNothingOutput {} } From 96bb46e64d7dded9fa5a608253f2124159234610 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Sat, 3 Dec 2022 13:47:44 +0100 Subject: [PATCH 06/18] Add Default impls Signed-off-by: Daniele Ahmed --- .../src/request/request_id.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index 9de0c801a3..d81c0d28b5 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -61,6 +61,13 @@ impl

FromParts

for ServerRequestId { parts.extensions.remove().ok_or(MissingServerRequestId) } } + +impl Default for ServerRequestId { + fn default() -> Self { + Self::new() + } +} + #[derive(Clone)] pub struct ServerRequestIdProvider { inner: S, @@ -74,6 +81,12 @@ impl ServerRequestIdProviderLayer { } } +impl Default for ServerRequestIdProviderLayer { + fn default() -> Self { + Self::new() + } +} + impl Layer for ServerRequestIdProviderLayer { type Service = ServerRequestIdProvider; From 81889b82ab324b0be7abae3385a43e87929d77ef Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 7 Dec 2022 10:38:56 +0100 Subject: [PATCH 07/18] Address comments Signed-off-by: Daniele Ahmed --- .../aws-smithy-http-server/Cargo.toml | 3 +- .../src/bin/pokemon-service-connect-info.rs | 14 ++-- .../aws-smithy-http-server/src/request/mod.rs | 2 + .../src/request/request_id.rs | 69 ++++++++++++++----- 4 files changed, 65 insertions(+), 23 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/Cargo.toml b/rust-runtime/aws-smithy-http-server/Cargo.toml index 7a1d6e81fe..9489ff0efb 100644 --- a/rust-runtime/aws-smithy-http-server/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server/Cargo.toml @@ -15,6 +15,7 @@ publish = true [features] aws-lambda = ["dep:lambda_http"] unredacted-logging = [] +request-id = ["dep:uuid"] [dependencies] aws-smithy-http = { path = "../aws-smithy-http", features = ["rt-tokio"] } @@ -41,7 +42,7 @@ tracing = "0.1.35" tokio = { version = "1.8.4", features = ["full"] } tower = { version = "0.4.11", features = ["util", "make"], default-features = false } tower-http = { version = "0.3", features = ["add-extension", "map-response-body"] } -uuid = { version = "1", features = ["v4", "fast-rng", "macro-diagnostics"] } +uuid = { version = "1", features = ["v4", "fast-rng", "macro-diagnostics"], optional = true } [dev-dependencies] pretty_assertions = "1" diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index e4502f63c7..bd0ba66e15 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -8,7 +8,7 @@ use std::net::{IpAddr, SocketAddr}; use aws_smithy_http_server::{ request::connect_info::ConnectInfo, request::request_id::ClientRequestId, request::request_id::ClientRequestIdProviderLayer, request::request_id::ServerRequestId, - request::request_id::ServerRequestIdProviderLayer, Extension, + request::request_id::ServerRequestIdProviderLayer, }; use clap::Parser; use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; @@ -59,13 +59,13 @@ pub async fn get_storage_with_local_approved( pub async fn do_nothing_but_log_request_ids( _input: DoNothingInput, - server_request_id: Extension, - client_request_id: Extension>, + server_request_id: ServerRequestId, + client_request_id: Option, ) -> DoNothingOutput { tracing::debug!( "This request has this client ID: {:?} and server ID: {}", - client_request_id.0, - server_request_id.0 + client_request_id, + server_request_id ); DoNothingOutput {} } @@ -85,7 +85,9 @@ async fn main() { .expect("failed to build an instance of PokemonService"); let app = app.layer(&ServerRequestIdProviderLayer::new()); - let app = app.layer(&ClientRequestIdProviderLayer::new(&["x-request-id"])); + let app = app.layer(&ClientRequestIdProviderLayer::new(&[std::borrow::Cow::Borrowed( + "x-request-id", + )])); // Start the [`hyper::Server`]. let bind: std::net::SocketAddr = format!("{}:{}", args.address, args.port) diff --git a/rust-runtime/aws-smithy-http-server/src/request/mod.rs b/rust-runtime/aws-smithy-http-server/src/request/mod.rs index 20e25743dd..0f397fd9bc 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/mod.rs @@ -59,6 +59,8 @@ pub mod extension; #[cfg(feature = "aws-lambda")] #[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))] pub mod lambda; +#[cfg(feature = "request-id")] +#[cfg_attr(docsrs, doc(cfg(feature = "request-id")))] pub mod request_id; fn internal_server_error() -> http::Response { diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index d81c0d28b5..bd9b6bae38 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -5,16 +5,47 @@ //! Request IDs //! -//! Request IDs are of two kinds: +//! RequestID is an element that uniquely identifies a client request. RequestID is used by services to map all logs, events and +//! specific data to a single operation. This RFC discusses whether and how smithy-rs can make that value available to customers. //! -//! * Client Request ID: the request ID sent from a client in the request header -//! * Server Request ID: the unique ID generated server-side for this request +//! Services use a RequestID to collect logs related to the same request and see its flow through the various operations, +//! help clients debug requests by sharing this value and, in some cases, use this value to perform their business logic. RequestID is unique across a service at least within a certain timeframe. //! -//! Both can be used at the same time and can be used as inputs in your operation handlers. -//! To use [`ClientRequestId`], specify which headers -//! may contain the client request ID. +//! RequestIDs are not to be used by multiple services, but only within a single service. +//! +//! For client request IDs, the process will be, in order: +//! * If a header is found matching one of the possible ones, use it +//! * Otherwise, None +//! +//! Server request IDs are opaque and generated by the service itself. +//! +//! Your handler can now optionally take as input a [`ServerRequestId`] and an [`Option`]. +//! +//! ```rust,ignore +//! pub async fn handler( +//! _input: Input, +//! server_request_id: ServerRequestId, +//! client_request_id: Option, +//! ) -> Output { +//! /* Use server_request_id and client_request_id */ +//! todo!() +//! } +//! +//! let app = Service::builder_without_plugins() +//! .operation(handler) +//! .build().unwrap(); +//! +//! let app = app.layer(&ServerRequestIdProviderLayer::new()); /* Generate a server request ID */ +//! let app = app.layer(&ClientRequestIdProviderLayer::new(&["x-request-id"])); /* Provide your handler with the client request ID */ +//! +//! let bind: std::net::SocketAddr = format!("{}:{}", args.address, args.port) +//! .parse() +//! .expect("unable to parse the server bind address and port"); +//! let server = hyper::Server::bind(&bind).serve(app.into_make_service()); +//! ``` use std::{ + borrow::{Borrow, Cow}, fmt::Display, task::{Context, Poll}, }; @@ -50,7 +81,7 @@ impl ServerRequestId { impl Display for ServerRequestId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.id) + self.id.fmt(f) } } @@ -73,9 +104,13 @@ pub struct ServerRequestIdProvider { inner: S, } -pub struct ServerRequestIdProviderLayer {} +/// A layer that provides services with a unique request ID instance +#[derive(Debug)] +#[non_exhaustive] +pub struct ServerRequestIdProviderLayer; impl ServerRequestIdProviderLayer { + /// Generate a new unique request ID pub fn new() -> Self { Self {} } @@ -95,9 +130,9 @@ impl Layer for ServerRequestIdProviderLayer { } } -impl Service> for ServerRequestIdProvider +impl Service> for ServerRequestIdProvider where - S: Service>, + S: Service>, { type Response = S::Response; type Error = S::Error; @@ -107,7 +142,7 @@ where self.inner.poll_ready(cx) } - fn call(&mut self, mut req: http::Request) -> Self::Future { + fn call(&mut self, mut req: http::Request) -> Self::Future { req.extensions_mut().insert(ServerRequestId::new()); self.inner.call(req) } @@ -134,6 +169,7 @@ pub struct ClientRequestId { pub struct MissingClientRequestId; impl ClientRequestId { + /// Wrap an incoming request ID from a client pub fn new(id: Box) -> Self { Self { id } } @@ -141,7 +177,7 @@ impl ClientRequestId { impl Display for ClientRequestId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.id) + self.id.fmt(f) } } @@ -156,15 +192,15 @@ impl

FromParts

for Option { #[derive(Clone)] pub struct ClientRequestIdProvider<'a, S> { inner: S, - possible_headers: &'a [&'a str], + possible_headers: &'a [Cow<'a, str>], } pub struct ClientRequestIdProviderLayer<'a> { - possible_headers: &'a [&'a str], + possible_headers: &'a [Cow<'a, str>], } impl<'a> ClientRequestIdProviderLayer<'a> { - pub fn new(possible_headers: &'a [&'a str]) -> Self { + pub fn new(possible_headers: &'a [Cow<'a, str>]) -> Self { Self { possible_headers } } } @@ -195,7 +231,8 @@ where fn call(&mut self, mut req: http::Request) -> Self::Future { let mut id: Option = None; for possible_header in self.possible_headers { - if let Some(value) = req.headers().get(*possible_header) { + let possible_header: &'a str = possible_header.borrow(); + if let Some(value) = req.headers().get(possible_header) { if let Ok(value) = value.to_str() { id = Some(ClientRequestId::new(value.into())); break; From 63959ac836703b0a82462f823d1c1ed9a811e173 Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Wed, 7 Dec 2022 10:11:52 +0000 Subject: [PATCH 08/18] Update rust-runtime/aws-smithy-http-server/Cargo.toml --- rust-runtime/aws-smithy-http-server/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/Cargo.toml b/rust-runtime/aws-smithy-http-server/Cargo.toml index 9489ff0efb..0c911bba21 100644 --- a/rust-runtime/aws-smithy-http-server/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server/Cargo.toml @@ -42,7 +42,7 @@ tracing = "0.1.35" tokio = { version = "1.8.4", features = ["full"] } tower = { version = "0.4.11", features = ["util", "make"], default-features = false } tower-http = { version = "0.3", features = ["add-extension", "map-response-body"] } -uuid = { version = "1", features = ["v4", "fast-rng", "macro-diagnostics"], optional = true } +uuid = { version = "1", features = ["v4", "fast-rng"], optional = true } [dev-dependencies] pretty_assertions = "1" From cd212e5501f33740cbff724b4f3d1005e6ecd4ec Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 7 Dec 2022 10:25:51 +0000 Subject: [PATCH 09/18] Update rust-runtime/aws-smithy-http-server/src/request/request_id.rs Co-authored-by: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> --- rust-runtime/aws-smithy-http-server/src/request/request_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index bd9b6bae38..d31d2b99cf 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -//! Request IDs +//! # Request IDs //! //! RequestID is an element that uniquely identifies a client request. RequestID is used by services to map all logs, events and //! specific data to a single operation. This RFC discusses whether and how smithy-rs can make that value available to customers. From 2dc211208372d1fd2e966ebeb5a2d709ea539637 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 7 Dec 2022 10:59:30 +0000 Subject: [PATCH 10/18] Update rust-runtime/aws-smithy-http-server/src/request/request_id.rs Co-authored-by: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> --- .../src/request/request_id.rs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index d31d2b99cf..244843631e 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -5,23 +5,31 @@ //! # Request IDs //! -//! RequestID is an element that uniquely identifies a client request. RequestID is used by services to map all logs, events and -//! specific data to a single operation. This RFC discusses whether and how smithy-rs can make that value available to customers. +//! `aws-smithy-http-server` provides two types of request ids: [`ServerRequestId`] and [`ClientRequestId`]. +//! +//! ## `ServerRequestId` +//! +//! A [`ServerRequestId`] is an opaque random identifier generated by the server every time it receives a request. +//! It uniquely identifies the request within that service instance. It can be used to collate all logs, events and +//! data related to a single operation. +//! +//! The [`ServerRequestId`] can be returned to the caller, who can in turn share the [`ServerRequestId`] to help the service owner in troubleshooting issues related to their usage of the service. //! -//! Services use a RequestID to collect logs related to the same request and see its flow through the various operations, -//! help clients debug requests by sharing this value and, in some cases, use this value to perform their business logic. RequestID is unique across a service at least within a certain timeframe. +//! The [`ServerRequestId`] is not meant to be propagated to downstream dependencies of the service. You should rely on a distributed tracing implementation for correlation purposes (e.g. OpenTelemetry). //! -//! RequestIDs are not to be used by multiple services, but only within a single service. +//! ## `ClientRequestId` //! -//! For client request IDs, the process will be, in order: -//! * If a header is found matching one of the possible ones, use it -//! * Otherwise, None +//! Clients can choose to provide their own identifier for the requests they are submitting. +//! [`ClientRequestId`] can be used by the service to extract the client-provided request id - usually for logging purposes. //! -//! Server request IDs are opaque and generated by the service itself. +//! We expect client request ids to be encoded as headers in the incoming request. The server will try to extract a value from the if a matching header is found. +//! Handlers and middlewares can use `Option` to leverage the client request id - it will be set to `Some` if one was found, `None` otherwise. +//! +//! ## Examples //! //! Your handler can now optionally take as input a [`ServerRequestId`] and an [`Option`]. //! -//! ```rust,ignore +//! ```rust //! pub async fn handler( //! _input: Input, //! server_request_id: ServerRequestId, @@ -36,7 +44,7 @@ //! .build().unwrap(); //! //! let app = app.layer(&ServerRequestIdProviderLayer::new()); /* Generate a server request ID */ -//! let app = app.layer(&ClientRequestIdProviderLayer::new(&["x-request-id"])); /* Provide your handler with the client request ID */ +//! let app = app.layer(&ClientRequestIdProviderLayer::new(&["x-request-id".into()])); /* Provide your handler with the client request ID */ //! //! let bind: std::net::SocketAddr = format!("{}:{}", args.address, args.port) //! .parse() From 355a102679952a29ebdf6a242be42275464758f0 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 7 Dec 2022 15:42:10 +0100 Subject: [PATCH 11/18] Use new Option impl for FromParts Signed-off-by: Daniele Ahmed --- .../src/request/request_id.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index 244843631e..658fda0765 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -6,25 +6,25 @@ //! # Request IDs //! //! `aws-smithy-http-server` provides two types of request ids: [`ServerRequestId`] and [`ClientRequestId`]. -//! +//! //! ## `ServerRequestId` -//! -//! A [`ServerRequestId`] is an opaque random identifier generated by the server every time it receives a request. +//! +//! A [`ServerRequestId`] is an opaque random identifier generated by the server every time it receives a request. //! It uniquely identifies the request within that service instance. It can be used to collate all logs, events and //! data related to a single operation. -//! +//! //! The [`ServerRequestId`] can be returned to the caller, who can in turn share the [`ServerRequestId`] to help the service owner in troubleshooting issues related to their usage of the service. //! -//! The [`ServerRequestId`] is not meant to be propagated to downstream dependencies of the service. You should rely on a distributed tracing implementation for correlation purposes (e.g. OpenTelemetry). +//! The [`ServerRequestId`] is not meant to be propagated to downstream dependencies of the service. You should rely on a distributed tracing implementation for correlation purposes (e.g. OpenTelemetry). //! //! ## `ClientRequestId` //! -//! Clients can choose to provide their own identifier for the requests they are submitting. +//! Clients can choose to provide their own identifier for the requests they are submitting. //! [`ClientRequestId`] can be used by the service to extract the client-provided request id - usually for logging purposes. //! //! We expect client request ids to be encoded as headers in the incoming request. The server will try to extract a value from the if a matching header is found. //! Handlers and middlewares can use `Option` to leverage the client request id - it will be set to `Some` if one was found, `None` otherwise. -//! +//! //! ## Examples //! //! Your handler can now optionally take as input a [`ServerRequestId`] and an [`Option`]. @@ -189,7 +189,7 @@ impl Display for ClientRequestId { } } -impl

FromParts

for Option { +impl

FromParts

for ClientRequestId { type Rejection = MissingClientRequestId; fn from_parts(parts: &mut Parts) -> Result { From 959114dc4bd091b3230641bf8489f4bf353ec678 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 20 Dec 2022 16:45:51 +0100 Subject: [PATCH 12/18] Remove ClientRequestId Signed-off-by: Daniele Ahmed --- design/src/rfcs/rfc0024_request_id.md | 9 +- .../src/bin/pokemon-service-connect-info.rs | 16 +-- .../src/request/request_id.rs | 112 +----------------- 3 files changed, 12 insertions(+), 125 deletions(-) diff --git a/design/src/rfcs/rfc0024_request_id.md b/design/src/rfcs/rfc0024_request_id.md index a69bdd11d7..a10d5e92e7 100644 --- a/design/src/rfcs/rfc0024_request_id.md +++ b/design/src/rfcs/rfc0024_request_id.md @@ -132,6 +132,11 @@ Changes checklist ----------------- - [x] Implement `ServerRequestId`: a `new()` function that generates a UUID, with `Display`, `Debug` and `ToStr` implementations -- [x] Implement `ClientRequestId`: `new()` that wraps a string (the header value) and the header in which the value could be found, with `Display`, `Debug` and `ToStr` implementations +- [ ] Implement `ClientRequestId`: `new()` that wraps a string (the header value) and the header in which the value could be found, with `Display`, `Debug` and `ToStr` implementations - [x] Implement `FromParts` for `Extension` -- [x] Implement `FromParts` for `Extension` +- [ ] Implement `FromParts` for `Extension` + +Changes since the RFC has been approved +--------------------------------------- + +This RFC has been changed to only implement `ServerRequestId`. diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index b990dc4a6f..8e74856607 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -5,11 +5,7 @@ use std::net::{IpAddr, SocketAddr}; -use aws_smithy_http_server::{ - request::connect_info::ConnectInfo, request::request_id::ClientRequestId, - request::request_id::ClientRequestIdProviderLayer, request::request_id::ServerRequestId, - request::request_id::ServerRequestIdProviderLayer, -}; +use aws_smithy_http_server::{request::request_id::ServerRequestId, request::request_id::ServerRequestIdProviderLayer}; use clap::Parser; use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; use pokemon_service_server_sdk::{ @@ -60,13 +56,8 @@ pub async fn get_storage_with_local_approved( pub async fn do_nothing_but_log_request_ids( _input: DoNothingInput, server_request_id: ServerRequestId, - client_request_id: Option, ) -> DoNothingOutput { - tracing::debug!( - "This request has this client ID: {:?} and server ID: {}", - client_request_id, - server_request_id - ); + tracing::debug!("This request has this server ID: {}", server_request_id); DoNothingOutput {} } @@ -85,9 +76,6 @@ async fn main() { .expect("failed to build an instance of PokemonService"); let app = app.layer(&ServerRequestIdProviderLayer::new()); - let app = app.layer(&ClientRequestIdProviderLayer::new(&[std::borrow::Cow::Borrowed( - "x-request-id", - )])); // Start the [`hyper::Server`]. let bind: SocketAddr = format!("{}:{}", args.address, args.port) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index 658fda0765..17e748a23e 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -5,7 +5,7 @@ //! # Request IDs //! -//! `aws-smithy-http-server` provides two types of request ids: [`ServerRequestId`] and [`ClientRequestId`]. +//! `aws-smithy-http-server` provides the [`ServerRequestId`]. //! //! ## `ServerRequestId` //! @@ -17,25 +17,16 @@ //! //! The [`ServerRequestId`] is not meant to be propagated to downstream dependencies of the service. You should rely on a distributed tracing implementation for correlation purposes (e.g. OpenTelemetry). //! -//! ## `ClientRequestId` -//! -//! Clients can choose to provide their own identifier for the requests they are submitting. -//! [`ClientRequestId`] can be used by the service to extract the client-provided request id - usually for logging purposes. -//! -//! We expect client request ids to be encoded as headers in the incoming request. The server will try to extract a value from the if a matching header is found. -//! Handlers and middlewares can use `Option` to leverage the client request id - it will be set to `Some` if one was found, `None` otherwise. -//! //! ## Examples //! -//! Your handler can now optionally take as input a [`ServerRequestId`] and an [`Option`]. +//! Your handler can now optionally take as input a [`ServerRequestId`]. //! //! ```rust //! pub async fn handler( //! _input: Input, //! server_request_id: ServerRequestId, -//! client_request_id: Option, //! ) -> Output { -//! /* Use server_request_id and client_request_id */ +//! /* Use server_request_id */ //! todo!() //! } //! @@ -44,7 +35,6 @@ //! .build().unwrap(); //! //! let app = app.layer(&ServerRequestIdProviderLayer::new()); /* Generate a server request ID */ -//! let app = app.layer(&ClientRequestIdProviderLayer::new(&["x-request-id".into()])); /* Provide your handler with the client request ID */ //! //! let bind: std::net::SocketAddr = format!("{}:{}", args.address, args.port) //! .parse() @@ -161,99 +151,3 @@ impl IntoResponse for MissingServerRequestId { internal_server_error() } } - -/// The Client Request ID. -/// -/// If it is missing, the request will be rejected with a `500 Internal Server Error` response. -#[derive(Clone, Debug)] -pub struct ClientRequestId { - id: Box, -} - -/// The client request ID has not been added to the [`Request`](http::Request) or has been previously removed. -#[non_exhaustive] -#[derive(Debug, Error)] -#[error("the `ClientRequestId` is not present in the `http::Request`")] -pub struct MissingClientRequestId; - -impl ClientRequestId { - /// Wrap an incoming request ID from a client - pub fn new(id: Box) -> Self { - Self { id } - } -} - -impl Display for ClientRequestId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.id.fmt(f) - } -} - -impl

FromParts

for ClientRequestId { - type Rejection = MissingClientRequestId; - - fn from_parts(parts: &mut Parts) -> Result { - parts.extensions.remove::().ok_or(MissingClientRequestId) - } -} - -#[derive(Clone)] -pub struct ClientRequestIdProvider<'a, S> { - inner: S, - possible_headers: &'a [Cow<'a, str>], -} - -pub struct ClientRequestIdProviderLayer<'a> { - possible_headers: &'a [Cow<'a, str>], -} - -impl<'a> ClientRequestIdProviderLayer<'a> { - pub fn new(possible_headers: &'a [Cow<'a, str>]) -> Self { - Self { possible_headers } - } -} - -impl<'a, S> Layer for ClientRequestIdProviderLayer<'a> { - type Service = ClientRequestIdProvider<'a, S>; - - fn layer(&self, inner: S) -> Self::Service { - ClientRequestIdProvider { - inner, - possible_headers: self.possible_headers, - } - } -} - -impl<'a, R, S> Service> for ClientRequestIdProvider<'a, S> -where - S: Service>, -{ - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, mut req: http::Request) -> Self::Future { - let mut id: Option = None; - for possible_header in self.possible_headers { - let possible_header: &'a str = possible_header.borrow(); - if let Some(value) = req.headers().get(possible_header) { - if let Ok(value) = value.to_str() { - id = Some(ClientRequestId::new(value.into())); - break; - } - } - } - req.extensions_mut().insert(id); - self.inner.call(req) - } -} - -impl IntoResponse for MissingClientRequestId { - fn into_response(self) -> http::Response { - internal_server_error() - } -} From 4d5cceddfa4c7340a184a934501a6938c754e69d Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 20 Dec 2022 16:56:07 +0100 Subject: [PATCH 13/18] Fix style Signed-off-by: Daniele Ahmed --- .../pokemon-service/src/bin/pokemon-service-connect-info.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index 8e74856607..b6e47b4274 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -5,7 +5,10 @@ use std::net::{IpAddr, SocketAddr}; -use aws_smithy_http_server::{request::request_id::ServerRequestId, request::request_id::ServerRequestIdProviderLayer}; +use aws_smithy_http_server::{ + request::connect_info::ConnectInfo, request::request_id::ServerRequestId, + request::request_id::ServerRequestIdProviderLayer, +}; use clap::Parser; use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; use pokemon_service_server_sdk::{ From 19bf72b1ed1f5ab28a48f68e9ac0fe730794ab3c Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 21 Dec 2022 16:26:20 +0100 Subject: [PATCH 14/18] Feature flag example Signed-off-by: Daniele Ahmed --- .../src/bin/pokemon-service-connect-info.rs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index b6e47b4274..dfc3c9b1d7 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -5,10 +5,9 @@ use std::net::{IpAddr, SocketAddr}; -use aws_smithy_http_server::{ - request::connect_info::ConnectInfo, request::request_id::ServerRequestId, - request::request_id::ServerRequestIdProviderLayer, -}; +use aws_smithy_http_server::request::connect_info::ConnectInfo; +#[cfg(feature = "request-id")] +use aws_smithy_http_server::{request::request_id::ServerRequestId, request::request_id::ServerRequestIdProviderLayer}; use clap::Parser; use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; use pokemon_service_server_sdk::{ @@ -56,13 +55,15 @@ pub async fn get_storage_with_local_approved( Err(GetStorageError::NotAuthorized(NotAuthorized {})) } -pub async fn do_nothing_but_log_request_ids( - _input: DoNothingInput, - server_request_id: ServerRequestId, -) -> DoNothingOutput { +#[cfg(feature = "request-id")] +pub async fn do_nothing(_input: DoNothingInput, server_request_id: ServerRequestId) -> DoNothingOutput { tracing::debug!("This request has this server ID: {}", server_request_id); DoNothingOutput {} } +#[cfg(not(feature = "request-id"))] +pub async fn do_nothing(_input: DoNothingInput) -> DoNothingOutput { + DoNothingOutput {} +} #[tokio::main] async fn main() { @@ -73,11 +74,12 @@ async fn main() { .get_storage(get_storage_with_local_approved) .get_server_statistics(get_server_statistics) .capture_pokemon(capture_pokemon) - .do_nothing(do_nothing_but_log_request_ids) + .do_nothing(do_nothing) .check_health(check_health) .build() .expect("failed to build an instance of PokemonService"); + #[cfg(feature = "request-id")] let app = app.layer(&ServerRequestIdProviderLayer::new()); // Start the [`hyper::Server`]. From 2a3d881f6967ce308117224472ba3fab1a612ffb Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 21 Dec 2022 16:37:17 +0100 Subject: [PATCH 15/18] Fix CI Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/request/request_id.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index 17e748a23e..f711a84dd8 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -43,7 +43,6 @@ //! ``` use std::{ - borrow::{Borrow, Cow}, fmt::Display, task::{Context, Poll}, }; From 13dada709e890b32d04e32a6e43cc2d3a6ac2919 Mon Sep 17 00:00:00 2001 From: Daniele Ahmed Date: Thu, 22 Dec 2022 12:35:15 +0100 Subject: [PATCH 16/18] Revert "Feature flag example" This reverts commit 19bf72b1ed1f5ab28a48f68e9ac0fe730794ab3c. --- .../src/bin/pokemon-service-connect-info.rs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs index dfc3c9b1d7..b6e47b4274 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs @@ -5,9 +5,10 @@ use std::net::{IpAddr, SocketAddr}; -use aws_smithy_http_server::request::connect_info::ConnectInfo; -#[cfg(feature = "request-id")] -use aws_smithy_http_server::{request::request_id::ServerRequestId, request::request_id::ServerRequestIdProviderLayer}; +use aws_smithy_http_server::{ + request::connect_info::ConnectInfo, request::request_id::ServerRequestId, + request::request_id::ServerRequestIdProviderLayer, +}; use clap::Parser; use pokemon_service::{capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing}; use pokemon_service_server_sdk::{ @@ -55,15 +56,13 @@ pub async fn get_storage_with_local_approved( Err(GetStorageError::NotAuthorized(NotAuthorized {})) } -#[cfg(feature = "request-id")] -pub async fn do_nothing(_input: DoNothingInput, server_request_id: ServerRequestId) -> DoNothingOutput { +pub async fn do_nothing_but_log_request_ids( + _input: DoNothingInput, + server_request_id: ServerRequestId, +) -> DoNothingOutput { tracing::debug!("This request has this server ID: {}", server_request_id); DoNothingOutput {} } -#[cfg(not(feature = "request-id"))] -pub async fn do_nothing(_input: DoNothingInput) -> DoNothingOutput { - DoNothingOutput {} -} #[tokio::main] async fn main() { @@ -74,12 +73,11 @@ async fn main() { .get_storage(get_storage_with_local_approved) .get_server_statistics(get_server_statistics) .capture_pokemon(capture_pokemon) - .do_nothing(do_nothing) + .do_nothing(do_nothing_but_log_request_ids) .check_health(check_health) .build() .expect("failed to build an instance of PokemonService"); - #[cfg(feature = "request-id")] let app = app.layer(&ServerRequestIdProviderLayer::new()); // Start the [`hyper::Server`]. From d58f7000e03ea25d37ac67916b0b1e588f3485b4 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 22 Dec 2022 12:38:17 +0100 Subject: [PATCH 17/18] Enable request-id flag in example Signed-off-by: Daniele Ahmed --- .../aws-smithy-http-server/examples/pokemon-service/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/Cargo.toml b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/Cargo.toml index 06738fcc54..da4cb284c0 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/Cargo.toml @@ -44,7 +44,7 @@ futures-util = "0.3" lambda_http = "0.7.1" # Local paths -aws-smithy-http-server = { path = "../../", features = ["aws-lambda"] } +aws-smithy-http-server = { path = "../../", features = ["aws-lambda", "request-id"] } pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/" } [dev-dependencies] From c25364ed6da593d1667060ec76592d1b606dd486 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:19:16 +0100 Subject: [PATCH 18/18] Ignore example doc Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/request/request_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs index f711a84dd8..7894d9806e 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/request_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/request_id.rs @@ -21,7 +21,7 @@ //! //! Your handler can now optionally take as input a [`ServerRequestId`]. //! -//! ```rust +//! ```rust,ignore //! pub async fn handler( //! _input: Input, //! server_request_id: ServerRequestId,