From 45c1cf82b505a73691b45bd8d099e888a8c91892 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 28 Apr 2023 15:23:35 +0200 Subject: [PATCH 01/16] OperationShape::NAME as ShapeId Signed-off-by: Daniele Ahmed --- .../src/bin/pokemon-service.rs | 6 +- .../examples/pokemon-service/src/plugin.rs | 9 +- .../aws-smithy-http-server/src/extension.rs | 115 +++++++++--------- .../src/instrumentation/layer.rs | 8 +- .../src/instrumentation/plugin.rs | 4 +- .../src/instrumentation/service.rs | 6 +- .../aws-smithy-http-server/src/lib.rs | 1 + .../src/operation/shape.rs | 3 +- .../src/plugin/closure.rs | 8 +- .../src/plugin/filter.rs | 5 +- .../aws-smithy-http-server/src/shape_id.rs | 45 +++++++ 11 files changed, 132 insertions(+), 78 deletions(-) create mode 100644 rust-runtime/aws-smithy-http-server/src/shape_id.rs diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs index 402e57555a..6317bae14d 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs @@ -6,7 +6,7 @@ // This program is exported as a binary named `pokemon-service`. use std::{net::SocketAddr, sync::Arc}; -use aws_smithy_http_server::{extension::OperationExtensionExt, plugin::PluginPipeline, AddExtensionLayer}; +use aws_smithy_http_server::{extension::OperationIdExt, plugin::PluginPipeline, AddExtensionLayer}; use clap::Parser; use pokemon_service::{ capture_pokemon, check_health, do_nothing, get_pokemon_species, get_server_statistics, get_storage, @@ -32,8 +32,8 @@ pub async fn main() { let plugins = PluginPipeline::new() // Apply the `PrintPlugin` defined in `plugin.rs` .print() - // Apply the `OperationExtensionPlugin` defined in `aws_smithy_http_server::extension`. This allows other - // plugins or tests to access a `aws_smithy_http_server::extension::OperationExtension` from + // Apply the `OperationIdPlugin` defined in `aws_smithy_http_server::extension`. This allows other + // plugins or tests to access a `aws_smithy_http_server::extension::OperationId` from // `Response::extensions`, or infer routing failure when it's missing. .insert_operation_extension(); let app = PokemonService::builder_with_plugins(plugins) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs index 8ce0e50d09..04f7ac28f7 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs @@ -12,12 +12,13 @@ use aws_smithy_http_server::{ use tower::{layer::util::Stack, Layer, Service}; use std::task::{Context, Poll}; +use aws_smithy_http_server::extension::OperationId; /// A [`Service`] that prints a given string. #[derive(Clone, Debug)] pub struct PrintService { inner: S, - name: &'static str, + name: OperationId, } impl Service for PrintService @@ -41,7 +42,7 @@ where /// A [`Layer`] which constructs the [`PrintService`]. #[derive(Debug)] pub struct PrintLayer { - name: &'static str, + name: OperationId, } impl Layer for PrintLayer { type Service = PrintService; @@ -49,7 +50,7 @@ impl Layer for PrintLayer { fn layer(&self, service: S) -> Self::Service { PrintService { inner: service, - name: self.name, + name: self.name.clone(), } } } @@ -66,7 +67,7 @@ where type Layer = Stack; fn map(&self, input: Operation) -> Operation { - input.layer(PrintLayer { name: Op::NAME }) + input.layer(PrintLayer { name: OperationId(Op::NAME) }) } } diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 2a8b664cdd..f3d0634b76 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -20,6 +20,8 @@ //! [extensions]: https://docs.rs/http/latest/http/struct.Extensions.html use std::{fmt, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll}; +use std::fmt::{Display, Formatter}; +use std::hash::{Hash, Hasher}; use futures_util::ready; use futures_util::TryFuture; @@ -28,20 +30,16 @@ use tower::{layer::util::Stack, Layer, Service}; use crate::operation::{Operation, OperationShape}; use crate::plugin::{plugin_from_operation_name_fn, OperationNameFn, Plugin, PluginPipeline, PluginStack}; +use crate::shape_id::ShapeId; pub use crate::request::extension::{Extension, MissingExtension}; /// Extension type used to store information about Smithy operations in HTTP responses. -/// This extension type is inserted, via the [`OperationExtensionPlugin`], whenever it has been correctly determined +/// This extension type is inserted, via the [`OperationIdPlugin`], whenever it has been correctly determined /// that the request should be routed to a particular operation. The operation handler might not even get invoked /// because the request fails to deserialize into the modeled operation input. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct OperationExtension { - absolute: &'static str, - - namespace: &'static str, - name: &'static str, -} +pub struct OperationId(pub ShapeId); /// An error occurred when parsing an absolute operation shape ID. #[derive(Debug, Clone, Error, PartialEq, Eq)] @@ -52,46 +50,46 @@ pub enum ParseError { } #[allow(deprecated)] -impl OperationExtension { - /// Creates a new [`OperationExtension`] from the absolute shape ID. - pub fn new(absolute_operation_id: &'static str) -> Result { - let (namespace, name) = absolute_operation_id - .rsplit_once('#') - .ok_or(ParseError::MissingNamespace)?; - Ok(Self { - absolute: absolute_operation_id, - namespace, - name, - }) - } - +impl OperationId { /// Returns the Smithy model namespace. pub fn namespace(&self) -> &'static str { - self.namespace + self.0.namespace() } /// Returns the Smithy operation name. pub fn name(&self) -> &'static str { - self.name + self.0.name() } /// Returns the absolute operation shape ID. pub fn absolute(&self) -> &'static str { - self.absolute + self.0.absolute() + } +} + +impl Display for OperationId { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0.absolute()) + } +} + +impl Hash for OperationId { + fn hash(&self, state: &mut H) { + self.0.absolute().hash(state) } } pin_project_lite::pin_project! { - /// The [`Service::Future`] of [`OperationExtensionService`] - inserts an [`OperationExtension`] into the + /// The [`Service::Future`] of [`OperationIdService`] - inserts an [`OperationId`] into the /// [`http::Response]`. - pub struct OperationExtensionFuture { + pub struct OperationIdFuture { #[pin] inner: Fut, - operation_extension: Option + operation_extension: Option } } -impl Future for OperationExtensionFuture +impl Future for OperationIdFuture where Fut: TryFuture>, { @@ -111,82 +109,81 @@ where } } -/// Inserts a [`OperationExtension`] into the extensions of the [`http::Response`]. +/// Inserts a [`OperationId`] into the extensions of the [`http::Response`]. #[derive(Debug, Clone)] -pub struct OperationExtensionService { +pub struct OperationIdService { inner: S, - operation_extension: OperationExtension, + operation_extension: OperationId, } -impl Service> for OperationExtensionService +impl Service> for OperationIdService where S: Service, Response = http::Response>, { type Response = http::Response; type Error = S::Error; - type Future = OperationExtensionFuture; + type Future = OperationIdFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, req: http::Request) -> Self::Future { - OperationExtensionFuture { + OperationIdFuture { inner: self.inner.call(req), operation_extension: Some(self.operation_extension.clone()), } } } -/// A [`Layer`] applying the [`OperationExtensionService`] to an inner [`Service`]. +/// A [`Layer`] applying the [`OperationIdService`] to an inner [`Service`]. #[derive(Debug, Clone)] -pub struct OperationExtensionLayer(OperationExtension); +pub struct OperationIdLayer(OperationId); -impl Layer for OperationExtensionLayer { - type Service = OperationExtensionService; +impl Layer for OperationIdLayer { + type Service = OperationIdService; fn layer(&self, inner: S) -> Self::Service { - OperationExtensionService { + OperationIdService { inner, operation_extension: self.0.clone(), } } } -/// A [`Plugin`] which applies [`OperationExtensionLayer`] to every operation. -pub struct OperationExtensionPlugin(OperationNameFn OperationExtensionLayer>); +/// A [`Plugin`] which applies [`OperationIdLayer`] to every operation. +pub struct OperationIdPlugin(OperationNameFn OperationIdLayer>); -impl fmt::Debug for OperationExtensionPlugin { +impl fmt::Debug for OperationIdPlugin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("OperationExtensionPlugin").field(&"...").finish() + f.debug_tuple("OperationIdPlugin").field(&"...").finish() } } -impl Plugin for OperationExtensionPlugin +impl Plugin for OperationIdPlugin where Op: OperationShape, { type Service = S; - type Layer = Stack; + type Layer = Stack; fn map(&self, input: Operation) -> Operation { - OperationExtensionLayer> as Plugin>::map(&self.0, input) + OperationIdLayer> as Plugin>::map(&self.0, input) } } -/// An extension trait on [`PluginPipeline`] allowing the application of [`OperationExtensionPlugin`]. +/// An extension trait on [`PluginPipeline`] allowing the application of [`OperationIdPlugin`]. /// /// See [`module`](crate::extension) documentation for more info. -pub trait OperationExtensionExt

{ - /// Apply the [`OperationExtensionPlugin`], which inserts the [`OperationExtension`] into every [`http::Response`]. - fn insert_operation_extension(self) -> PluginPipeline>; +pub trait OperationIdExt

{ + /// Apply the [`OperationIdPlugin`], which inserts the [`OperationId`] into every [`http::Response`]. + fn insert_operation_extension(self) -> PluginPipeline>; } -impl

OperationExtensionExt

for PluginPipeline

{ - fn insert_operation_extension(self) -> PluginPipeline> { - let plugin = OperationExtensionPlugin(plugin_from_operation_name_fn(|name| { - let operation_extension = OperationExtension::new(name).expect("Operation name is malformed, this should never happen. Please file an issue against https://github.com/awslabs/smithy-rs"); - OperationExtensionLayer(operation_extension) +impl

OperationIdExt

for PluginPipeline

{ + fn insert_operation_extension(self) -> PluginPipeline> { + let plugin = OperationIdPlugin(plugin_from_operation_name_fn(|shape_id| { + OperationIdLayer(shape_id.clone()) })); self.push(plugin) } @@ -243,7 +240,7 @@ mod tests { #[test] fn ext_accept() { let value = "com.amazonaws.ebs#CompleteSnapshot"; - let ext = OperationExtension::new(value).unwrap(); + let ext = OperationId::new(value).unwrap(); assert_eq!(ext.absolute(), value); assert_eq!(ext.namespace(), "com.amazonaws.ebs"); @@ -254,7 +251,7 @@ mod tests { fn ext_reject() { let value = "CompleteSnapshot"; assert_eq!( - OperationExtension::new(value).unwrap_err(), + OperationId::new(value).unwrap_err(), ParseError::MissingNamespace ) } @@ -281,10 +278,10 @@ mod tests { let svc = service_fn(|_: http::Request<()>| async { Ok::<_, ()>(http::Response::new(())) }); let svc = layer.layer(svc); - // Check for `OperationExtension`. + // Check for `OperationId`. let response = svc.oneshot(http::Request::new(())).await.unwrap(); - let expected = OperationExtension::new(DummyOp::NAME).unwrap(); - let actual = response.extensions().get::().unwrap(); + let expected = OperationId::new(DummyOp::NAME).unwrap(); + let actual = response.extensions().get::().unwrap(); assert_eq!(*actual, expected); } } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs index 956fd6b24d..6bc5ec776d 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs @@ -5,19 +5,21 @@ use tower::Layer; +use crate::extension::OperationId; + use super::{InstrumentOperation, MakeIdentity}; /// A [`Layer`] used to apply [`InstrumentOperation`]. #[derive(Debug)] pub struct InstrumentLayer { - operation_name: &'static str, + operation_name: OperationId, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentLayer { /// Constructs a new [`InstrumentLayer`] with no data redacted. - pub fn new(operation_name: &'static str) -> Self { + pub fn new(operation_name: OperationId) -> Self { Self { operation_name, make_request: MakeIdentity, @@ -58,7 +60,7 @@ where type Service = InstrumentOperation; fn layer(&self, service: S) -> Self::Service { - InstrumentOperation::new(service, self.operation_name) + InstrumentOperation::new(service, self.operation_name.clone()) .request_fmt(self.make_request.clone()) .response_fmt(self.make_response.clone()) } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs index ce77218603..a6b7b52a06 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs @@ -7,6 +7,7 @@ use tower::layer::util::Stack; use crate::plugin::{PluginPipeline, PluginStack}; use crate::{ + extension::OperationId, operation::{Operation, OperationShape}, plugin::Plugin, }; @@ -26,7 +27,8 @@ where type Layer = Stack>; fn map(&self, operation: Operation) -> Operation { - let layer = InstrumentLayer::new(Op::NAME) + let operation_id = OperationId(Op::NAME); + let layer = InstrumentLayer::new(operation_id) .request_fmt(Op::request_fmt()) .response_fmt(Op::response_fmt()); operation.layer(layer) diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs index 32fabd47cb..59448f97fe 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs @@ -16,6 +16,8 @@ use http::{HeaderMap, Request, Response, StatusCode, Uri}; use tower::Service; use tracing::{debug, debug_span, instrument::Instrumented, Instrument}; +use crate::extension::OperationId; + use super::{MakeDebug, MakeDisplay, MakeIdentity}; pin_project_lite::pin_project! { @@ -103,14 +105,14 @@ where #[derive(Debug, Clone)] pub struct InstrumentOperation { inner: S, - operation_name: &'static str, + operation_name: OperationId, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentOperation { /// Constructs a new [`InstrumentOperation`] with no data redacted. - pub fn new(inner: S, operation_name: &'static str) -> Self { + pub fn new(inner: S, operation_name: OperationId) -> Self { Self { inner, operation_name, diff --git a/rust-runtime/aws-smithy-http-server/src/lib.rs b/rust-runtime/aws-smithy-http-server/src/lib.rs index 6031c53e2a..c6d1175c37 100644 --- a/rust-runtime/aws-smithy-http-server/src/lib.rs +++ b/rust-runtime/aws-smithy-http-server/src/lib.rs @@ -28,6 +28,7 @@ pub mod response; pub mod routing; #[doc(hidden)] pub mod runtime_error; +pub mod shape_id; #[doc(inline)] pub(crate) use self::error::Error; diff --git a/rust-runtime/aws-smithy-http-server/src/operation/shape.rs b/rust-runtime/aws-smithy-http-server/src/operation/shape.rs index 9990326279..73c914a443 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/shape.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/shape.rs @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +use crate::shape_id::ShapeId; use super::{Handler, IntoService, Normalize, Operation, OperationService}; /// Models the [Smithy Operation shape]. @@ -10,7 +11,7 @@ use super::{Handler, IntoService, Normalize, Operation, OperationService}; /// [Smithy Operation shape]: https://awslabs.github.io/smithy/1.0/spec/core/model.html#operation pub trait OperationShape { /// The name of the operation. - const NAME: &'static str; + const NAME: ShapeId; /// The operation input. type Input; diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs index 75685c97b9..35f26be26e 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs @@ -6,6 +6,7 @@ use tower::layer::util::Stack; use crate::operation::{Operation, OperationShape}; +use crate::extension::OperationId; use super::Plugin; @@ -16,14 +17,15 @@ pub struct OperationNameFn { impl Plugin for OperationNameFn where - F: Fn(&'static str) -> NewLayer, + F: Fn(OperationId) -> NewLayer, Op: OperationShape, { type Service = S; type Layer = Stack; fn map(&self, input: Operation) -> Operation { - input.layer((self.f)(Op::NAME)) + let operation_id = OperationId(Op::NAME); + input.layer((self.f)(operation_id)) } } @@ -55,7 +57,7 @@ where /// ``` pub fn plugin_from_operation_name_fn(f: F) -> OperationNameFn where - F: Fn(&'static str) -> L, + F: Fn(OperationId) -> L, { OperationNameFn { f } } diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs b/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs index a9804169b8..db8c20e762 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs @@ -6,6 +6,7 @@ use tower::util::Either; use crate::operation::{Operation, OperationShape}; +use crate::shape_id::ShapeId; use super::Plugin; @@ -38,7 +39,7 @@ pub struct FilterByOperationName { /// ``` pub fn filter_by_operation_name(plugins: Inner, predicate: F) -> FilterByOperationName where - F: Fn(&str) -> bool, + F: Fn(ShapeId) -> bool, { FilterByOperationName::new(plugins, predicate) } @@ -52,7 +53,7 @@ impl FilterByOperationName { impl Plugin for FilterByOperationName where - F: Fn(&str) -> bool, + F: Fn(ShapeId) -> bool, Inner: Plugin, Op: OperationShape, { diff --git a/rust-runtime/aws-smithy-http-server/src/shape_id.rs b/rust-runtime/aws-smithy-http-server/src/shape_id.rs new file mode 100644 index 0000000000..985c42e527 --- /dev/null +++ b/rust-runtime/aws-smithy-http-server/src/shape_id.rs @@ -0,0 +1,45 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Extension types. +//! +//! Shape ID is a type that describes a Smithy shape. +//! + +pub use crate::request::extension::{Extension, MissingExtension}; + +/// Shape ID for a modelled Smithy shape. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ShapeId { + absolute: &'static str, + + namespace: &'static str, + name: &'static str, +} + +impl ShapeId { + pub const fn new(absolute: &'static str, namespace: &'static str, name: &'static str) -> Self { + Self { + absolute, + namespace, + name, + } + } + + /// Returns the Smithy model namespace. + pub fn namespace(&self) -> &'static str { + self.namespace + } + + /// Returns the Smithy operation name. + pub fn name(&self) -> &'static str { + self.name + } + + /// Returns the absolute operation shape ID. + pub fn absolute(&self) -> &'static str { + self.absolute + } +} \ No newline at end of file From 3671a415db965dc862897900c862fd130820d715 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 9 May 2023 16:50:40 +0200 Subject: [PATCH 02/16] Address comments Signed-off-by: Daniele Ahmed --- .../generators/ServerOperationGenerator.kt | 4 +- .../generators/ServerServiceGeneratorV2.kt | 7 +- .../src/bin/pokemon-service.rs | 6 +- .../examples/pokemon-service/src/plugin.rs | 8 +- .../aws-smithy-http-server/src/extension.rs | 90 +++++++++---------- .../src/instrumentation/layer.rs | 6 +- .../src/instrumentation/plugin.rs | 4 +- .../src/instrumentation/service.rs | 6 +- .../src/plugin/closure.rs | 8 +- .../aws-smithy-http-server/src/shape_id.rs | 5 +- 10 files changed, 71 insertions(+), 73 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt index 4589de74a5..5287464b11 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt @@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext +import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCargoDependency @@ -49,12 +50,13 @@ class ServerOperationGenerator( val requestFmt = generator.requestFmt() val responseFmt = generator.responseFmt() + val operationIdAbsolute = operationId.toString().replace("#", "##") writer.rustTemplate( """ pub struct $operationName; impl #{SmithyHttpServer}::operation::OperationShape for $operationName { - const NAME: &'static str = "${operationId.toString().replace("#", "##")}"; + const NAME: #{SmithyHttpServer}::shape_id::ShapeId = #{SmithyHttpServer}::shape_id::ShapeId::new(${operationIdAbsolute.dq()}, ${operationId.namespace.dq()}, ${operationId.name.dq()}); type Input = crate::input::${operationName}Input; type Output = crate::output::${operationName}Output; diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt index 3b7d09c3ce..926927b268 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt @@ -478,13 +478,13 @@ class ServerServiceGeneratorV2( } private fun missingOperationsError(): Writable = writable { - rust( + rustTemplate( """ /// The error encountered when calling the [`$builderName::build`] method if one or more operation handlers are not /// specified. ##[derive(Debug)] pub struct MissingOperationsError { - operation_names2setter_methods: std::collections::HashMap<&'static str, &'static str>, + operation_names2setter_methods: std::collections::HashMap<#{SmithyHttpServer}::shape_id::ShapeId, &'static str>, } impl std::fmt::Display for MissingOperationsError { @@ -495,7 +495,7 @@ class ServerServiceGeneratorV2( We are missing handlers for the following operations:\n", )?; for operation_name in self.operation_names2setter_methods.keys() { - writeln!(f, "- {}", operation_name)?; + writeln!(f, "- {}", operation_name.absolute())?; } writeln!(f, "\nUse the dedicated methods on `$builderName` to register the missing handlers:")?; @@ -508,6 +508,7 @@ class ServerServiceGeneratorV2( impl std::error::Error for MissingOperationsError {} """, + *codegenScope, ) } diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs index 6317bae14d..402e57555a 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service.rs @@ -6,7 +6,7 @@ // This program is exported as a binary named `pokemon-service`. use std::{net::SocketAddr, sync::Arc}; -use aws_smithy_http_server::{extension::OperationIdExt, plugin::PluginPipeline, AddExtensionLayer}; +use aws_smithy_http_server::{extension::OperationExtensionExt, plugin::PluginPipeline, AddExtensionLayer}; use clap::Parser; use pokemon_service::{ capture_pokemon, check_health, do_nothing, get_pokemon_species, get_server_statistics, get_storage, @@ -32,8 +32,8 @@ pub async fn main() { let plugins = PluginPipeline::new() // Apply the `PrintPlugin` defined in `plugin.rs` .print() - // Apply the `OperationIdPlugin` defined in `aws_smithy_http_server::extension`. This allows other - // plugins or tests to access a `aws_smithy_http_server::extension::OperationId` from + // Apply the `OperationExtensionPlugin` defined in `aws_smithy_http_server::extension`. This allows other + // plugins or tests to access a `aws_smithy_http_server::extension::OperationExtension` from // `Response::extensions`, or infer routing failure when it's missing. .insert_operation_extension(); let app = PokemonService::builder_with_plugins(plugins) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs index 04f7ac28f7..52dd8996c6 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs @@ -12,13 +12,13 @@ use aws_smithy_http_server::{ use tower::{layer::util::Stack, Layer, Service}; use std::task::{Context, Poll}; -use aws_smithy_http_server::extension::OperationId; +use aws_smithy_http_server::extension::OperationExtension; /// A [`Service`] that prints a given string. #[derive(Clone, Debug)] pub struct PrintService { inner: S, - name: OperationId, + name: OperationExtension, } impl Service for PrintService @@ -42,7 +42,7 @@ where /// A [`Layer`] which constructs the [`PrintService`]. #[derive(Debug)] pub struct PrintLayer { - name: OperationId, + name: OperationExtension, } impl Layer for PrintLayer { type Service = PrintService; @@ -67,7 +67,7 @@ where type Layer = Stack; fn map(&self, input: Operation) -> Operation { - input.layer(PrintLayer { name: OperationId(Op::NAME) }) + input.layer(PrintLayer { name: OperationExtension(Op::NAME) }) } } diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index f3d0634b76..e5e3743e0f 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -19,9 +19,9 @@ //! //! [extensions]: https://docs.rs/http/latest/http/struct.Extensions.html -use std::{fmt, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll}; +use std::{fmt, fmt::Debug, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll}; use std::fmt::{Display, Formatter}; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use futures_util::ready; use futures_util::TryFuture; @@ -35,11 +35,11 @@ use crate::shape_id::ShapeId; pub use crate::request::extension::{Extension, MissingExtension}; /// Extension type used to store information about Smithy operations in HTTP responses. -/// This extension type is inserted, via the [`OperationIdPlugin`], whenever it has been correctly determined +/// This extension type is inserted, via the [`OperationExtensionPlugin`], whenever it has been correctly determined /// that the request should be routed to a particular operation. The operation handler might not even get invoked /// because the request fails to deserialize into the modeled operation input. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct OperationId(pub ShapeId); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct OperationExtension(pub ShapeId); /// An error occurred when parsing an absolute operation shape ID. #[derive(Debug, Clone, Error, PartialEq, Eq)] @@ -50,7 +50,7 @@ pub enum ParseError { } #[allow(deprecated)] -impl OperationId { +impl OperationExtension { /// Returns the Smithy model namespace. pub fn namespace(&self) -> &'static str { self.0.namespace() @@ -67,29 +67,23 @@ impl OperationId { } } -impl Display for OperationId { +impl Display for OperationExtension { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.absolute()) - } -} - -impl Hash for OperationId { - fn hash(&self, state: &mut H) { - self.0.absolute().hash(state) + self.0.fmt(f) } } pin_project_lite::pin_project! { - /// The [`Service::Future`] of [`OperationIdService`] - inserts an [`OperationId`] into the + /// The [`Service::Future`] of [`OperationExtensionService`] - inserts an [`OperationExtension`] into the /// [`http::Response]`. - pub struct OperationIdFuture { + pub struct OperationExtensionFuture { #[pin] inner: Fut, - operation_extension: Option + operation_extension: Option } } -impl Future for OperationIdFuture +impl Future for OperationExtensionFuture where Fut: TryFuture>, { @@ -109,81 +103,81 @@ where } } -/// Inserts a [`OperationId`] into the extensions of the [`http::Response`]. +/// Inserts a [`OperationExtension`] into the extensions of the [`http::Response`]. #[derive(Debug, Clone)] -pub struct OperationIdService { +pub struct OperationExtensionService { inner: S, - operation_extension: OperationId, + operation_extension: OperationExtension, } -impl Service> for OperationIdService +impl Service> for OperationExtensionService where S: Service, Response = http::Response>, { type Response = http::Response; type Error = S::Error; - type Future = OperationIdFuture; + type Future = OperationExtensionFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, req: http::Request) -> Self::Future { - OperationIdFuture { + OperationExtensionFuture { inner: self.inner.call(req), operation_extension: Some(self.operation_extension.clone()), } } } -/// A [`Layer`] applying the [`OperationIdService`] to an inner [`Service`]. +/// A [`Layer`] applying the [`OperationExtensionService`] to an inner [`Service`]. #[derive(Debug, Clone)] -pub struct OperationIdLayer(OperationId); +pub struct OperationExtensionLayer(OperationExtension); -impl Layer for OperationIdLayer { - type Service = OperationIdService; +impl Layer for OperationExtensionLayer { + type Service = OperationExtensionService; fn layer(&self, inner: S) -> Self::Service { - OperationIdService { + OperationExtensionService { inner, operation_extension: self.0.clone(), } } } -/// A [`Plugin`] which applies [`OperationIdLayer`] to every operation. -pub struct OperationIdPlugin(OperationNameFn OperationIdLayer>); +/// A [`Plugin`] which applies [`OperationExtensionLayer`] to every operation. +pub struct OperationExtensionPlugin(OperationNameFn OperationExtensionLayer>); -impl fmt::Debug for OperationIdPlugin { +impl fmt::Debug for OperationExtensionPlugin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("OperationIdPlugin").field(&"...").finish() + f.debug_tuple("OperationExtensionPlugin").field(&"...").finish() } } -impl Plugin for OperationIdPlugin +impl Plugin for OperationExtensionPlugin where Op: OperationShape, { type Service = S; - type Layer = Stack; + type Layer = Stack; fn map(&self, input: Operation) -> Operation { - OperationIdLayer> as Plugin>::map(&self.0, input) + OperationExtensionLayer> as Plugin>::map(&self.0, input) } } -/// An extension trait on [`PluginPipeline`] allowing the application of [`OperationIdPlugin`]. +/// An extension trait on [`PluginPipeline`] allowing the application of [`OperationExtensionPlugin`]. /// /// See [`module`](crate::extension) documentation for more info. -pub trait OperationIdExt

{ - /// Apply the [`OperationIdPlugin`], which inserts the [`OperationId`] into every [`http::Response`]. - fn insert_operation_extension(self) -> PluginPipeline>; +pub trait OperationExtensionExt

{ + /// Apply the [`OperationExtensionPlugin`], which inserts the [`OperationExtension`] into every [`http::Response`]. + fn insert_operation_extension(self) -> PluginPipeline>; } -impl

OperationIdExt

for PluginPipeline

{ - fn insert_operation_extension(self) -> PluginPipeline> { - let plugin = OperationIdPlugin(plugin_from_operation_name_fn(|shape_id| { - OperationIdLayer(shape_id.clone()) +impl

OperationExtensionExt

for PluginPipeline

{ + fn insert_operation_extension(self) -> PluginPipeline> { + let plugin = OperationExtensionPlugin(plugin_from_operation_name_fn(|shape_id| { + OperationExtensionLayer(shape_id.clone()) })); self.push(plugin) } @@ -240,7 +234,7 @@ mod tests { #[test] fn ext_accept() { let value = "com.amazonaws.ebs#CompleteSnapshot"; - let ext = OperationId::new(value).unwrap(); + let ext = OperationExtension::new(value).unwrap(); assert_eq!(ext.absolute(), value); assert_eq!(ext.namespace(), "com.amazonaws.ebs"); @@ -251,7 +245,7 @@ mod tests { fn ext_reject() { let value = "CompleteSnapshot"; assert_eq!( - OperationId::new(value).unwrap_err(), + OperationExtension::new(value).unwrap_err(), ParseError::MissingNamespace ) } @@ -280,8 +274,8 @@ mod tests { // Check for `OperationId`. let response = svc.oneshot(http::Request::new(())).await.unwrap(); - let expected = OperationId::new(DummyOp::NAME).unwrap(); - let actual = response.extensions().get::().unwrap(); + let expected = OperationExtension::new(DummyOp::NAME).unwrap(); + let actual = response.extensions().get::().unwrap(); assert_eq!(*actual, expected); } } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs index 6bc5ec776d..35b63d41e9 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs @@ -5,21 +5,21 @@ use tower::Layer; -use crate::extension::OperationId; +use crate::extension::OperationExtension; use super::{InstrumentOperation, MakeIdentity}; /// A [`Layer`] used to apply [`InstrumentOperation`]. #[derive(Debug)] pub struct InstrumentLayer { - operation_name: OperationId, + operation_name: OperationExtension, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentLayer { /// Constructs a new [`InstrumentLayer`] with no data redacted. - pub fn new(operation_name: OperationId) -> Self { + pub fn new(operation_name: OperationExtension) -> Self { Self { operation_name, make_request: MakeIdentity, diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs index a6b7b52a06..dcde0ebfd1 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs @@ -7,7 +7,7 @@ use tower::layer::util::Stack; use crate::plugin::{PluginPipeline, PluginStack}; use crate::{ - extension::OperationId, + extension::OperationExtension, operation::{Operation, OperationShape}, plugin::Plugin, }; @@ -27,7 +27,7 @@ where type Layer = Stack>; fn map(&self, operation: Operation) -> Operation { - let operation_id = OperationId(Op::NAME); + let operation_id = OperationExtension(Op::NAME); let layer = InstrumentLayer::new(operation_id) .request_fmt(Op::request_fmt()) .response_fmt(Op::response_fmt()); diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs index 59448f97fe..09a45aef82 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs @@ -16,7 +16,7 @@ use http::{HeaderMap, Request, Response, StatusCode, Uri}; use tower::Service; use tracing::{debug, debug_span, instrument::Instrumented, Instrument}; -use crate::extension::OperationId; +use crate::extension::OperationExtension; use super::{MakeDebug, MakeDisplay, MakeIdentity}; @@ -105,14 +105,14 @@ where #[derive(Debug, Clone)] pub struct InstrumentOperation { inner: S, - operation_name: OperationId, + operation_name: OperationExtension, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentOperation { /// Constructs a new [`InstrumentOperation`] with no data redacted. - pub fn new(inner: S, operation_name: OperationId) -> Self { + pub fn new(inner: S, operation_name: OperationExtension) -> Self { Self { inner, operation_name, diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs index 35f26be26e..82cbc0ed77 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs @@ -6,7 +6,7 @@ use tower::layer::util::Stack; use crate::operation::{Operation, OperationShape}; -use crate::extension::OperationId; +use crate::extension::OperationExtension; use super::Plugin; @@ -17,14 +17,14 @@ pub struct OperationNameFn { impl Plugin for OperationNameFn where - F: Fn(OperationId) -> NewLayer, + F: Fn(OperationExtension) -> NewLayer, Op: OperationShape, { type Service = S; type Layer = Stack; fn map(&self, input: Operation) -> Operation { - let operation_id = OperationId(Op::NAME); + let operation_id = OperationExtension(Op::NAME); input.layer((self.f)(operation_id)) } } @@ -57,7 +57,7 @@ where /// ``` pub fn plugin_from_operation_name_fn(f: F) -> OperationNameFn where - F: Fn(OperationId) -> L, + F: Fn(OperationExtension) -> L, { OperationNameFn { f } } diff --git a/rust-runtime/aws-smithy-http-server/src/shape_id.rs b/rust-runtime/aws-smithy-http-server/src/shape_id.rs index 985c42e527..d310b7548f 100644 --- a/rust-runtime/aws-smithy-http-server/src/shape_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/shape_id.rs @@ -11,7 +11,7 @@ pub use crate::request::extension::{Extension, MissingExtension}; /// Shape ID for a modelled Smithy shape. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ShapeId { absolute: &'static str, @@ -20,6 +20,7 @@ pub struct ShapeId { } impl ShapeId { + #[doc(hidden)] pub const fn new(absolute: &'static str, namespace: &'static str, name: &'static str) -> Self { Self { absolute, @@ -42,4 +43,4 @@ impl ShapeId { pub fn absolute(&self) -> &'static str { self.absolute } -} \ No newline at end of file +} From 005083f340f2fc2628d157deb658120b8a3745ed Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 9 May 2023 17:01:56 +0200 Subject: [PATCH 03/16] update references Signed-off-by: Daniele Ahmed --- .../examples/pokemon-service/src/plugin.rs | 12 ++++++------ .../src/instrumentation/layer.rs | 8 ++++---- .../src/instrumentation/service.rs | 8 ++++---- .../aws-smithy-http-server/src/plugin/mod.rs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs index 52dd8996c6..ea6ee09d91 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs @@ -8,17 +8,17 @@ use aws_smithy_http_server::{ operation::{Operation, OperationShape}, plugin::{Plugin, PluginPipeline, PluginStack}, + shape_id::ShapeId, }; use tower::{layer::util::Stack, Layer, Service}; use std::task::{Context, Poll}; -use aws_smithy_http_server::extension::OperationExtension; /// A [`Service`] that prints a given string. #[derive(Clone, Debug)] pub struct PrintService { inner: S, - name: OperationExtension, + id: ShapeId, } impl Service for PrintService @@ -34,7 +34,7 @@ where } fn call(&mut self, req: R) -> Self::Future { - println!("Hi {}", self.name); + println!("Hi {}", self.id.absolute()); self.inner.call(req) } } @@ -42,7 +42,7 @@ where /// A [`Layer`] which constructs the [`PrintService`]. #[derive(Debug)] pub struct PrintLayer { - name: OperationExtension, + id: ShapeId, } impl Layer for PrintLayer { type Service = PrintService; @@ -50,7 +50,7 @@ impl Layer for PrintLayer { fn layer(&self, service: S) -> Self::Service { PrintService { inner: service, - name: self.name.clone(), + id: self.id.clone(), } } } @@ -67,7 +67,7 @@ where type Layer = Stack; fn map(&self, input: Operation) -> Operation { - input.layer(PrintLayer { name: OperationExtension(Op::NAME) }) + input.layer(PrintLayer { id: Op::NAME }) } } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs index 35b63d41e9..cc326750fc 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs @@ -5,23 +5,23 @@ use tower::Layer; -use crate::extension::OperationExtension; +use crate::shape_id::ShapeId; use super::{InstrumentOperation, MakeIdentity}; /// A [`Layer`] used to apply [`InstrumentOperation`]. #[derive(Debug)] pub struct InstrumentLayer { - operation_name: OperationExtension, + operation_id: ShapepId, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentLayer { /// Constructs a new [`InstrumentLayer`] with no data redacted. - pub fn new(operation_name: OperationExtension) -> Self { + pub fn new(operation_id: ShapeId) -> Self { Self { - operation_name, + operation_id, make_request: MakeIdentity, make_response: MakeIdentity, } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs index 09a45aef82..4085d05e28 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs @@ -16,7 +16,7 @@ use http::{HeaderMap, Request, Response, StatusCode, Uri}; use tower::Service; use tracing::{debug, debug_span, instrument::Instrumented, Instrument}; -use crate::extension::OperationExtension; +use crate::shape_id::ShapeId; use super::{MakeDebug, MakeDisplay, MakeIdentity}; @@ -105,17 +105,17 @@ where #[derive(Debug, Clone)] pub struct InstrumentOperation { inner: S, - operation_name: OperationExtension, + operation_id: ShapepId, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentOperation { /// Constructs a new [`InstrumentOperation`] with no data redacted. - pub fn new(inner: S, operation_name: OperationExtension) -> Self { + pub fn new(inner: S, operation_id: OperationExtension) -> Self { Self { inner, - operation_name, + operation_id, make_request: MakeIdentity, make_response: MakeIdentity, } diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs index 6e43d4b493..3cc40dbeb3 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs @@ -79,7 +79,7 @@ //! } //! //! fn call(&mut self, req: R) -> Self::Future { -//! println!("Hi {}", self.name); +//! println!("Hi {}", self.id.absolute()); //! self.inner.call(req) //! } //! } From 70f986554ede320a91dd06df9e5aec21420cbc68 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 9 May 2023 17:39:56 +0200 Subject: [PATCH 04/16] update to use shapeid Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/extension.rs | 7 ++++--- .../src/instrumentation/layer.rs | 8 ++++---- .../src/instrumentation/plugin.rs | 3 +-- .../src/instrumentation/service.rs | 10 +++++----- .../aws-smithy-http-server/src/plugin/closure.rs | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index e5e3743e0f..452d65bea9 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -27,6 +27,7 @@ use futures_util::ready; use futures_util::TryFuture; use thiserror::Error; use tower::{layer::util::Stack, Layer, Service}; +use crate::extension; use crate::operation::{Operation, OperationShape}; use crate::plugin::{plugin_from_operation_name_fn, OperationNameFn, Plugin, PluginPipeline, PluginStack}; @@ -146,7 +147,7 @@ impl Layer for OperationExtensionLayer { } /// A [`Plugin`] which applies [`OperationExtensionLayer`] to every operation. -pub struct OperationExtensionPlugin(OperationNameFn OperationExtensionLayer>); +pub struct OperationExtensionPlugin(OperationNameFn OperationExtensionLayer>); impl fmt::Debug for OperationExtensionPlugin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -162,7 +163,7 @@ where type Layer = Stack; fn map(&self, input: Operation) -> Operation { - OperationExtensionLayer> as Plugin>::map(&self.0, input) + OperationExtensionLayer> as Plugin>::map(&self.0, input) } } @@ -177,7 +178,7 @@ pub trait OperationExtensionExt

{ impl

OperationExtensionExt

for PluginPipeline

{ fn insert_operation_extension(self) -> PluginPipeline> { let plugin = OperationExtensionPlugin(plugin_from_operation_name_fn(|shape_id| { - OperationExtensionLayer(shape_id.clone()) + OperationExtensionLayer(extension::OperationExtension(shape_id.clone())) })); self.push(plugin) } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs index cc326750fc..c070d1297e 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/layer.rs @@ -12,7 +12,7 @@ use super::{InstrumentOperation, MakeIdentity}; /// A [`Layer`] used to apply [`InstrumentOperation`]. #[derive(Debug)] pub struct InstrumentLayer { - operation_id: ShapepId, + operation_id: ShapeId, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } @@ -34,7 +34,7 @@ impl InstrumentLayer(self, make_request: R) -> InstrumentLayer { InstrumentLayer { - operation_name: self.operation_name, + operation_id: self.operation_id, make_request, make_response: self.make_response, } @@ -45,7 +45,7 @@ impl InstrumentLayer(self, make_response: R) -> InstrumentLayer { InstrumentLayer { - operation_name: self.operation_name, + operation_id: self.operation_id, make_request: self.make_request, make_response, } @@ -60,7 +60,7 @@ where type Service = InstrumentOperation; fn layer(&self, service: S) -> Self::Service { - InstrumentOperation::new(service, self.operation_name.clone()) + InstrumentOperation::new(service, self.operation_id.clone()) .request_fmt(self.make_request.clone()) .response_fmt(self.make_response.clone()) } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs index dcde0ebfd1..7da5e2fbeb 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs @@ -7,7 +7,6 @@ use tower::layer::util::Stack; use crate::plugin::{PluginPipeline, PluginStack}; use crate::{ - extension::OperationExtension, operation::{Operation, OperationShape}, plugin::Plugin, }; @@ -27,7 +26,7 @@ where type Layer = Stack>; fn map(&self, operation: Operation) -> Operation { - let operation_id = OperationExtension(Op::NAME); + let operation_id = Op::NAME; let layer = InstrumentLayer::new(operation_id) .request_fmt(Op::request_fmt()) .response_fmt(Op::response_fmt()); diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs index 4085d05e28..4d09f687c3 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs @@ -105,14 +105,14 @@ where #[derive(Debug, Clone)] pub struct InstrumentOperation { inner: S, - operation_id: ShapepId, + operation_id: ShapeId, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } impl InstrumentOperation { /// Constructs a new [`InstrumentOperation`] with no data redacted. - pub fn new(inner: S, operation_id: OperationExtension) -> Self { + pub fn new(inner: S, operation_id: ShapeId) -> Self { Self { inner, operation_id, @@ -129,7 +129,7 @@ impl InstrumentOperation(self, make_request: R) -> InstrumentOperation { InstrumentOperation { inner: self.inner, - operation_name: self.operation_name, + operation_id: self.operation_id, make_request, make_response: self.make_response, } @@ -141,7 +141,7 @@ impl InstrumentOperation(self, make_response: R) -> InstrumentOperation { InstrumentOperation { inner: self.inner, - operation_name: self.operation_name, + operation_id: self.operation_id, make_request: self.make_request, make_response, } @@ -172,7 +172,7 @@ where let span = { let headers = self.make_request.make_debug(request.headers()); let uri = self.make_request.make_display(request.uri()); - debug_span!("request", operation = %self.operation_name, method = %request.method(), %uri, ?headers) + debug_span!("request", operation = %self.operation_id.absolute(), method = %request.method(), %uri, ?headers) }; InstrumentedFuture { diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs index 82cbc0ed77..fc850392ec 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs @@ -6,7 +6,7 @@ use tower::layer::util::Stack; use crate::operation::{Operation, OperationShape}; -use crate::extension::OperationExtension; +use crate::shape_id::ShapeId; use super::Plugin; @@ -17,14 +17,14 @@ pub struct OperationNameFn { impl Plugin for OperationNameFn where - F: Fn(OperationExtension) -> NewLayer, + F: Fn(ShapeId) -> NewLayer, Op: OperationShape, { type Service = S; type Layer = Stack; fn map(&self, input: Operation) -> Operation { - let operation_id = OperationExtension(Op::NAME); + let operation_id = Op::NAME; input.layer((self.f)(operation_id)) } } @@ -57,7 +57,7 @@ where /// ``` pub fn plugin_from_operation_name_fn(f: F) -> OperationNameFn where - F: Fn(OperationExtension) -> L, + F: Fn(ShapeId) -> L, { OperationNameFn { f } } From cdbdb94fecaa2fb368ce84a022a0c5647279417c Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 10:29:17 +0200 Subject: [PATCH 05/16] update to main Signed-off-by: Daniele Ahmed --- .../server/smithy/generators/ServerServiceGenerator.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt index 160f9fd685..d78a7aa903 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt @@ -478,13 +478,13 @@ class ServerServiceGenerator( } private fun missingOperationsError(): Writable = writable { - rust( + rustTemplate( """ /// The error encountered when calling the [`$builderName::build`] method if one or more operation handlers are not /// specified. ##[derive(Debug)] pub struct MissingOperationsError { - operation_names2setter_methods: std::collections::HashMap<&'static str, &'static str>, + operation_names2setter_methods: std::collections::HashMap<#{SmithyHttpServer}::shape_id::ShapeId, &'static str>, } impl std::fmt::Display for MissingOperationsError { @@ -495,7 +495,7 @@ class ServerServiceGenerator( We are missing handlers for the following operations:\n", )?; for operation_name in self.operation_names2setter_methods.keys() { - writeln!(f, "- {}", operation_name)?; + writeln!(f, "- {}", operation_name.absolute())?; } writeln!(f, "\nUse the dedicated methods on `$builderName` to register the missing handlers:")?; @@ -508,6 +508,7 @@ class ServerServiceGenerator( impl std::error::Error for MissingOperationsError {} """, + *codegenScope, ) } From 4368d3ab8905b47e97d95c143fa348876c408ce7 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 10:30:15 +0200 Subject: [PATCH 06/16] address comment Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/extension.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 452d65bea9..7bdf4eb8d6 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -273,7 +273,7 @@ mod tests { let svc = service_fn(|_: http::Request<()>| async { Ok::<_, ()>(http::Response::new(())) }); let svc = layer.layer(svc); - // Check for `OperationId`. + // Check for `OperationExtension`. let response = svc.oneshot(http::Request::new(())).await.unwrap(); let expected = OperationExtension::new(DummyOp::NAME).unwrap(); let actual = response.extensions().get::().unwrap(); From f752f29e771ffde73faa81677ba9b4c73bf28b03 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 12:43:55 +0200 Subject: [PATCH 07/16] Address comments Signed-off-by: Daniele Ahmed --- .../aws-smithy-http-server/src/extension.rs | 31 ++----------------- .../src/plugin/closure.rs | 10 +++--- .../src/plugin/filter.rs | 18 +++++------ .../aws-smithy-http-server/src/plugin/mod.rs | 6 ++-- .../src/plugin/pipeline.rs | 6 ++-- .../aws-smithy-http-server/src/shape_id.rs | 1 + 6 files changed, 24 insertions(+), 48 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 7bdf4eb8d6..3a92735c9b 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -20,7 +20,6 @@ //! [extensions]: https://docs.rs/http/latest/http/struct.Extensions.html use std::{fmt, fmt::Debug, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll}; -use std::fmt::{Display, Formatter}; use std::hash::Hash; use futures_util::ready; @@ -30,7 +29,7 @@ use tower::{layer::util::Stack, Layer, Service}; use crate::extension; use crate::operation::{Operation, OperationShape}; -use crate::plugin::{plugin_from_operation_name_fn, OperationNameFn, Plugin, PluginPipeline, PluginStack}; +use crate::plugin::{plugin_from_operation_name_fn, OperationIdFn, Plugin, PluginPipeline, PluginStack}; use crate::shape_id::ShapeId; pub use crate::request::extension::{Extension, MissingExtension}; @@ -50,30 +49,6 @@ pub enum ParseError { MissingNamespace, } -#[allow(deprecated)] -impl OperationExtension { - /// Returns the Smithy model namespace. - pub fn namespace(&self) -> &'static str { - self.0.namespace() - } - - /// Returns the Smithy operation name. - pub fn name(&self) -> &'static str { - self.0.name() - } - - /// Returns the absolute operation shape ID. - pub fn absolute(&self) -> &'static str { - self.0.absolute() - } -} - -impl Display for OperationExtension { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - pin_project_lite::pin_project! { /// The [`Service::Future`] of [`OperationExtensionService`] - inserts an [`OperationExtension`] into the /// [`http::Response]`. @@ -147,7 +122,7 @@ impl Layer for OperationExtensionLayer { } /// A [`Plugin`] which applies [`OperationExtensionLayer`] to every operation. -pub struct OperationExtensionPlugin(OperationNameFn OperationExtensionLayer>); +pub struct OperationExtensionPlugin(OperationIdFn OperationExtensionLayer>); impl fmt::Debug for OperationExtensionPlugin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -163,7 +138,7 @@ where type Layer = Stack; fn map(&self, input: Operation) -> Operation { - OperationExtensionLayer> as Plugin>::map(&self.0, input) + OperationExtensionLayer> as Plugin>::map(&self.0, input) } } diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs index fc850392ec..3510b24021 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs @@ -11,11 +11,11 @@ use crate::shape_id::ShapeId; use super::Plugin; /// An adapter to convert a `Fn(&'static str) -> Layer` closure into a [`Plugin`]. See [`plugin_from_operation_name_fn`] for more details. -pub struct OperationNameFn { +pub struct OperationIdFn { f: F, } -impl Plugin for OperationNameFn +impl Plugin for OperationIdFn where F: Fn(ShapeId) -> NewLayer, Op: OperationShape, @@ -53,11 +53,11 @@ where /// let f = |operation_name| PrintLayer { operation_name }; /// /// // This plugin applies the `PrintService` middleware around every operation. -/// let plugin = plugin_from_operation_name_fn(f); +/// let plugin = plugin_from_operation_id_fn(f); /// ``` -pub fn plugin_from_operation_name_fn(f: F) -> OperationNameFn +pub fn plugin_from_operation_id_fn(f: F) -> OperationIdFn where F: Fn(ShapeId) -> L, { - OperationNameFn { f } + OperationIdFn { f } } diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs b/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs index a4f0d3fc20..2d82aced60 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs @@ -13,8 +13,8 @@ use super::Plugin; /// Filters the application of an inner [`Plugin`] using a predicate over the /// [`OperationShape::NAME`](crate::operation::OperationShape). /// -/// See [`filter_by_operation_name`] for more details. -pub struct FilterByOperationName { +/// See [`filter_by_operation_id`] for more details. +pub struct FilterByOperationId { inner: Inner, predicate: F, } @@ -25,7 +25,7 @@ pub struct FilterByOperationName { /// # Example /// /// ```rust -/// use aws_smithy_http_server::plugin::filter_by_operation_name; +/// use aws_smithy_http_server::plugin::filter_by_operation_id; /// # use aws_smithy_http_server::{plugin::Plugin, operation::{Operation, OperationShape}}; /// # struct Pl; /// # struct CheckHealth; @@ -34,24 +34,24 @@ pub struct FilterByOperationName { /// # let plugin = Pl; /// # let operation = Operation { inner: (), layer: () }; /// // Prevents `plugin` from being applied to the `CheckHealth` operation. -/// let filtered_plugin = filter_by_operation_name(plugin, |name| name != CheckHealth::NAME); +/// let filtered_plugin = filter_by_operation_id(plugin, |name| name != CheckHealth::NAME); /// let new_operation = filtered_plugin.map(operation); /// ``` -pub fn filter_by_operation_name(plugins: Inner, predicate: F) -> FilterByOperationName +pub fn filter_by_operation_id(plugins: Inner, predicate: F) -> FilterByOperationId where F: Fn(ShapeId) -> bool, { - FilterByOperationName::new(plugins, predicate) + FilterByOperationId::new(plugins, predicate) } -impl FilterByOperationName { - /// Creates a new [`FilterByOperationName`]. +impl FilterByOperationId { + /// Creates a new [`FilterByOperationId`]. fn new(inner: Inner, predicate: F) -> Self { Self { inner, predicate } } } -impl Plugin for FilterByOperationName +impl Plugin for FilterByOperationId where F: Fn(ShapeId) -> bool, Inner: Plugin, diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs index 3015fff144..0f2f56804e 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs @@ -19,7 +19,7 @@ //! let plugin = HttpLayer(layer); //! //! // Only apply the layer to operations with name "GetPokemonSpecies" -//! let plugin = filter_by_operation_name(plugin, |name| name == GetPokemonSpecies::NAME); +//! let plugin = filter_by_operation_id(plugin, |name| name == GetPokemonSpecies::NAME); //! ``` //! //! # Construct a [`Plugin`] from a closure that takes as input the operation name @@ -129,9 +129,9 @@ mod stack; use crate::operation::Operation; -pub use closure::{plugin_from_operation_name_fn, OperationNameFn}; +pub use closure::{plugin_from_operation_id_fn, OperationIdFn}; pub use either::Either; -pub use filter::{filter_by_operation_name, FilterByOperationName}; +pub use filter::{filter_by_operation_id, FilterByOperationId}; pub use identity::IdentityPlugin; pub use layer::HttpLayer; pub use pipeline::PluginPipeline; diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs b/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs index 2a956922e4..14f63ddab7 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs @@ -35,11 +35,11 @@ use super::HttpLayer; /// /// `PluginPipeline` is itself a [`Plugin`]: you can apply any transformation that expects a /// [`Plugin`] to an entire pipeline. In this case, we want to use -/// [`filter_by_operation_name`](crate::plugin::filter_by_operation_name) to limit the scope of +/// [`filter_by_operation_name`](crate::plugin::filter_by_operation_id) to limit the scope of /// the logging and metrics plugins to the `CheckHealth` operation: /// /// ```rust -/// use aws_smithy_http_server::plugin::{filter_by_operation_name, PluginPipeline}; +/// use aws_smithy_http_server::plugin::{filter_by_operation_id, PluginPipeline}; /// # use aws_smithy_http_server::plugin::IdentityPlugin as LoggingPlugin; /// # use aws_smithy_http_server::plugin::IdentityPlugin as MetricsPlugin; /// # use aws_smithy_http_server::plugin::IdentityPlugin as AuthPlugin; @@ -47,7 +47,7 @@ use super::HttpLayer; /// # impl CheckHealth { const NAME: &'static str = "MyName"; } /// /// // The logging and metrics plugins will only be applied to the `CheckHealth` operation. -/// let operation_specific_pipeline = filter_by_operation_name( +/// let operation_specific_pipeline = filter_by_operation_id( /// PluginPipeline::new() /// .push(LoggingPlugin) /// .push(MetricsPlugin), diff --git a/rust-runtime/aws-smithy-http-server/src/shape_id.rs b/rust-runtime/aws-smithy-http-server/src/shape_id.rs index d310b7548f..860b95dfef 100644 --- a/rust-runtime/aws-smithy-http-server/src/shape_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/shape_id.rs @@ -20,6 +20,7 @@ pub struct ShapeId { } impl ShapeId { + /// Constructs a new [`ShapeId`]. This is used by the code-generator which preserves the invariants of the Shape ID format. #[doc(hidden)] pub const fn new(absolute: &'static str, namespace: &'static str, name: &'static str) -> Self { Self { From 2fb39b698261195074b909f51686df19f1e9cf0d Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 13:17:53 +0200 Subject: [PATCH 08/16] changelog Signed-off-by: Daniele Ahmed --- CHANGELOG.next.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index d85ecdf734..b48d9647ce 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -23,3 +23,12 @@ message = "Implement `Ord` and `PartialOrd` for `DateTime`." author = "henriiik" references = ["smithy-rs#2653", "smithy-rs#2656"] meta = { "breaking" = false, "tada" = false, "bug" = false } + +[[smithy-rs]] +message = """`ShapeId` is the new structure used to represent a shape, with its absolute name, namespace and name. +`OperationExtension`'s members are replaced by the `ShapeId` and operations' names are now replced by a `ShapeId`. +""" +author = "82marbag" +references = ["smithy-rs#2678"] +meta = { "breaking" = true, "tada" = false, "bug" = false } + From c4ed6805598558720174fd3e01827d8603dd3412 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 14:37:15 +0200 Subject: [PATCH 09/16] fix renaming Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/extension.rs | 4 ++-- rust-runtime/aws-smithy-http-server/src/plugin/closure.rs | 4 ++-- rust-runtime/aws-smithy-http-server/src/plugin/mod.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 3a92735c9b..08c4fb1b14 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -29,7 +29,7 @@ use tower::{layer::util::Stack, Layer, Service}; use crate::extension; use crate::operation::{Operation, OperationShape}; -use crate::plugin::{plugin_from_operation_name_fn, OperationIdFn, Plugin, PluginPipeline, PluginStack}; +use crate::plugin::{plugin_from_operation_id_fn, OperationIdFn, Plugin, PluginPipeline, PluginStack}; use crate::shape_id::ShapeId; pub use crate::request::extension::{Extension, MissingExtension}; @@ -152,7 +152,7 @@ pub trait OperationExtensionExt

{ impl

OperationExtensionExt

for PluginPipeline

{ fn insert_operation_extension(self) -> PluginPipeline> { - let plugin = OperationExtensionPlugin(plugin_from_operation_name_fn(|shape_id| { + let plugin = OperationExtensionPlugin(plugin_from_operation_id_fn(|shape_id| { OperationExtensionLayer(extension::OperationExtension(shape_id.clone())) })); self.push(plugin) diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs index 3510b24021..2e8c3bca60 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs @@ -10,7 +10,7 @@ use crate::shape_id::ShapeId; use super::Plugin; -/// An adapter to convert a `Fn(&'static str) -> Layer` closure into a [`Plugin`]. See [`plugin_from_operation_name_fn`] for more details. +/// An adapter to convert a `Fn(&'static str) -> Layer` closure into a [`Plugin`]. See [`plugin_from_operation_id_fn`] for more details. pub struct OperationIdFn { f: F, } @@ -35,7 +35,7 @@ where /// # Example /// /// ```rust -/// use aws_smithy_http_server::plugin::plugin_from_operation_name_fn; +/// use aws_smithy_http_server::plugin::plugin_from_operation_id_fn; /// use tower::layer::layer_fn; /// /// // A `Service` which prints the operation name before calling `S`. diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs index 0f2f56804e..4d6ab87f16 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs @@ -32,7 +32,7 @@ //! } //! //! // Create a `Plugin` using `PrintLayer` -//! let plugin = plugin_from_operation_name_fn(|name| PrintLayer { name }); +//! let plugin = plugin_from_operation_id_fn(|name| PrintLayer { name }); //! ``` //! //! # Combine [`Plugin`]s From b6de66096e67da3f9b401b76c4a8549a7a7ebd43 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 15:18:10 +0200 Subject: [PATCH 10/16] remove redundant clone Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/extension.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 08c4fb1b14..c27fd3ed51 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -153,7 +153,7 @@ pub trait OperationExtensionExt

{ impl

OperationExtensionExt

for PluginPipeline

{ fn insert_operation_extension(self) -> PluginPipeline> { let plugin = OperationExtensionPlugin(plugin_from_operation_id_fn(|shape_id| { - OperationExtensionLayer(extension::OperationExtension(shape_id.clone())) + OperationExtensionLayer(extension::OperationExtension(shape_id)) })); self.push(plugin) } From 09d94701f9909f2afab3920416cd2250e3a66f2f Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 15:59:47 +0200 Subject: [PATCH 11/16] fix ci tests Signed-off-by: Daniele Ahmed --- .../aws-smithy-http-server/src/extension.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index c27fd3ed51..69396cd738 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -210,28 +210,19 @@ mod tests { #[test] fn ext_accept() { let value = "com.amazonaws.ebs#CompleteSnapshot"; - let ext = OperationExtension::new(value).unwrap(); + let ext = ShapeId::new("com.amazonaws.ebs#CompleteSnapshot", "com.amazonaws.ebs", "CompleteSnapshot"); assert_eq!(ext.absolute(), value); assert_eq!(ext.namespace(), "com.amazonaws.ebs"); assert_eq!(ext.name(), "CompleteSnapshot"); } - #[test] - fn ext_reject() { - let value = "CompleteSnapshot"; - assert_eq!( - OperationExtension::new(value).unwrap_err(), - ParseError::MissingNamespace - ) - } - #[tokio::test] async fn plugin() { struct DummyOp; impl OperationShape for DummyOp { - const NAME: &'static str = "com.amazonaws.ebs#CompleteSnapshot"; + const NAME: ShapeId = ShapeId::new("com.amazonaws.ebs#CompleteSnapshot", "com.amazonaws.ebs", "CompleteSnapshot"); type Input = (); type Output = (); @@ -250,7 +241,7 @@ mod tests { // Check for `OperationExtension`. let response = svc.oneshot(http::Request::new(())).await.unwrap(); - let expected = OperationExtension::new(DummyOp::NAME).unwrap(); + let expected = DummyOp::NAME; let actual = response.extensions().get::().unwrap(); assert_eq!(*actual, expected); } From e48f72d37b73aa42e5af4f0cdb1232c695b681aa Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 10 May 2023 16:22:22 +0200 Subject: [PATCH 12/16] fix test Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/extension.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 69396cd738..91dc5411cf 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -243,6 +243,6 @@ mod tests { let response = svc.oneshot(http::Request::new(())).await.unwrap(); let expected = DummyOp::NAME; let actual = response.extensions().get::().unwrap(); - assert_eq!(*actual, expected); + assert_eq!(actual.0, expected); } } From 640fc972c7b8c56325f6f7b5269d7bdc47b2268c Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 11 May 2023 10:19:08 +0200 Subject: [PATCH 13/16] fix ci Signed-off-by: Daniele Ahmed --- .../aws-smithy-http-server/src/extension.rs | 16 ++++++++++++---- .../aws-smithy-http-server/src/operation/mod.rs | 7 ++++--- .../src/operation/shape.rs | 2 +- .../aws-smithy-http-server/src/plugin/mod.rs | 3 ++- .../src/plugin/pipeline.rs | 5 +++-- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 91dc5411cf..371df01529 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -19,14 +19,14 @@ //! //! [extensions]: https://docs.rs/http/latest/http/struct.Extensions.html -use std::{fmt, fmt::Debug, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll}; use std::hash::Hash; +use std::{fmt, fmt::Debug, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll}; +use crate::extension; use futures_util::ready; use futures_util::TryFuture; use thiserror::Error; use tower::{layer::util::Stack, Layer, Service}; -use crate::extension; use crate::operation::{Operation, OperationShape}; use crate::plugin::{plugin_from_operation_id_fn, OperationIdFn, Plugin, PluginPipeline, PluginStack}; @@ -210,7 +210,11 @@ mod tests { #[test] fn ext_accept() { let value = "com.amazonaws.ebs#CompleteSnapshot"; - let ext = ShapeId::new("com.amazonaws.ebs#CompleteSnapshot", "com.amazonaws.ebs", "CompleteSnapshot"); + let ext = ShapeId::new( + "com.amazonaws.ebs#CompleteSnapshot", + "com.amazonaws.ebs", + "CompleteSnapshot", + ); assert_eq!(ext.absolute(), value); assert_eq!(ext.namespace(), "com.amazonaws.ebs"); @@ -222,7 +226,11 @@ mod tests { struct DummyOp; impl OperationShape for DummyOp { - const NAME: ShapeId = ShapeId::new("com.amazonaws.ebs#CompleteSnapshot", "com.amazonaws.ebs", "CompleteSnapshot"); + const NAME: ShapeId = ShapeId::new( + "com.amazonaws.ebs#CompleteSnapshot", + "com.amazonaws.ebs", + "CompleteSnapshot", + ); type Input = (); type Output = (); diff --git a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs index 3abf9e2540..118e2c125f 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs @@ -24,14 +24,14 @@ //! is identified with the implementation //! //! ```rust,no_run -//! # use aws_smithy_http_server::operation::OperationShape; +//! # use aws_smithy_http_server::shape_id::ShapeId; //! # pub struct CartIdentifier; //! # pub struct ShoppingCart; //! # pub enum GetShoppingError {} //! pub struct GetShopping; //! //! impl OperationShape for GetShopping { -//! const NAME: &'static str = "GetShopping"; +//! const NAME: ShapeId = ShapeId::new("namespace#GetShopping", "namespace", "GetShopping"); //! //! type Input = CartIdentifier; //! type Output = ShoppingCart; @@ -105,12 +105,13 @@ //! # use std::task::{Poll, Context}; //! # use aws_smithy_http_server::operation::*; //! # use tower::Service; +//! # use aws_smithy_http_server::shape_id::ShapeId; //! # pub struct CartIdentifier; //! # pub struct ShoppingCart; //! # pub enum GetShoppingError {} //! # pub struct GetShopping; //! # impl OperationShape for GetShopping { -//! # const NAME: &'static str = "GetShopping"; +//! # const NAME: ShapeId = ShapeId::new("namespace#GetShopping", "namespace", "GetShopping"); //! # //! # type Input = CartIdentifier; //! # type Output = ShoppingCart; diff --git a/rust-runtime/aws-smithy-http-server/src/operation/shape.rs b/rust-runtime/aws-smithy-http-server/src/operation/shape.rs index 73c914a443..40a915a35b 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/shape.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/shape.rs @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -use crate::shape_id::ShapeId; use super::{Handler, IntoService, Normalize, Operation, OperationService}; +use crate::shape_id::ShapeId; /// Models the [Smithy Operation shape]. /// diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs index 4d6ab87f16..c97057f293 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs @@ -55,6 +55,7 @@ //! use aws_smithy_http_server::{ //! operation::{Operation, OperationShape}, //! plugin::{Plugin, PluginPipeline, PluginStack}, +//! shape_id::ShapeId, //! }; //! # use tower::{layer::util::Stack, Layer, Service}; //! # use std::task::{Context, Poll}; @@ -63,7 +64,7 @@ //! #[derive(Clone, Debug)] //! pub struct PrintService { //! inner: S, -//! name: &'static str, +//! id: ShapeId, //! } //! //! impl Service for PrintService diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs b/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs index 14f63ddab7..d38ecfd782 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/pipeline.rs @@ -43,8 +43,9 @@ use super::HttpLayer; /// # use aws_smithy_http_server::plugin::IdentityPlugin as LoggingPlugin; /// # use aws_smithy_http_server::plugin::IdentityPlugin as MetricsPlugin; /// # use aws_smithy_http_server::plugin::IdentityPlugin as AuthPlugin; +/// use aws_smithy_http_server::shape_id::ShapeId; /// # struct CheckHealth; -/// # impl CheckHealth { const NAME: &'static str = "MyName"; } +/// # impl CheckHealth { const NAME: ShapeId = ShapeId::new("namespace#MyName", "namespace", "MyName"); } /// /// // The logging and metrics plugins will only be applied to the `CheckHealth` operation. /// let operation_specific_pipeline = filter_by_operation_id( @@ -156,7 +157,7 @@ impl

PluginPipeline

{ /// { /// // [...] /// fn map(&self, input: Operation) -> Operation { - /// input.layer(PrintLayer { name: Op::NAME }) + /// input.layer(PrintLayer { id: Op::NAME }) /// } /// } /// ``` From 46563451cd5dce2924581fab41582dbc0eb2fae3 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 11 May 2023 13:43:27 +0200 Subject: [PATCH 14/16] fix docs Signed-off-by: Daniele Ahmed --- .../src/instrumentation/mod.rs | 4 +++- .../src/instrumentation/service.rs | 4 +++- .../aws-smithy-http-server/src/plugin/closure.rs | 9 +++++---- .../aws-smithy-http-server/src/plugin/filter.rs | 3 ++- .../aws-smithy-http-server/src/plugin/mod.rs | 12 +++++++----- rust-runtime/aws-smithy-http-server/src/shape_id.rs | 2 +- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs index 72fd2af2e6..2519e10137 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs @@ -13,6 +13,7 @@ //! ``` //! # use std::convert::Infallible; //! # use aws_smithy_http_server::instrumentation::{*, sensitivity::{*, headers::*, uri::*}}; +//! # use aws_smithy_http_server::shape_id::ShapeId; //! # use http::{Request, Response}; //! # use tower::{util::service_fn, Service}; //! # async fn service(request: Request<()>) -> Result, Infallible> { @@ -20,6 +21,7 @@ //! # } //! # async fn example() { //! # let service = service_fn(service); +//! # const NAME: ShapeId = ShapeId::new("namespace#foo-operation", "namespace", "foo-operation"); //! let request = Request::get("http://localhost/a/b/c/d?bar=hidden") //! .header("header-name-a", "hidden") //! .body(()) @@ -47,7 +49,7 @@ //! } //! }) //! .status_code(); -//! let mut service = InstrumentOperation::new(service, "foo-operation") +//! let mut service = InstrumentOperation::new(service, NAME) //! .request_fmt(request_fmt) //! .response_fmt(response_fmt); //! diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs index 8b3e2ccbd5..76410cfa65 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs @@ -89,15 +89,17 @@ where /// /// ``` /// # use aws_smithy_http_server::instrumentation::{sensitivity::{*, uri::*, headers::*}, *}; +/// # use aws_smithy_http_server::shape_id::ShapeId; /// # use tower::{Service, service_fn}; /// # use http::{Request, Response}; /// # async fn f(request: Request<()>) -> Result, ()> { Ok(Response::new(())) } /// # let mut svc = service_fn(f); +/// # const NAME: ShapeId = ShapeId::new("namespace#foo-operation", "namespace", "foo-operation"); /// let request_fmt = RequestFmt::new() /// .label(|index| index == 1, None) /// .query(|_| QueryMarker { key: false, value: true }); /// let response_fmt = ResponseFmt::new().status_code(); -/// let mut svc = InstrumentOperation::new(svc, "foo-operation") +/// let mut svc = InstrumentOperation::new(svc, NAME) /// .request_fmt(request_fmt) /// .response_fmt(response_fmt); /// # svc.call(Request::new(())); diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs index 2e8c3bca60..f1f5951e8a 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/closure.rs @@ -10,7 +10,7 @@ use crate::shape_id::ShapeId; use super::Plugin; -/// An adapter to convert a `Fn(&'static str) -> Layer` closure into a [`Plugin`]. See [`plugin_from_operation_id_fn`] for more details. +/// An adapter to convert a `Fn(ShapeId) -> Layer` closure into a [`Plugin`]. See [`plugin_from_operation_id_fn`] for more details. pub struct OperationIdFn { f: F, } @@ -29,24 +29,25 @@ where } } -/// Constructs a [`Plugin`] using a closure over the operation name `F: Fn(&'static str) -> L` where `L` is a HTTP +/// Constructs a [`Plugin`] using a closure over the operation name `F: Fn(ShapeId) -> L` where `L` is a HTTP /// [`Layer`](tower::Layer). /// /// # Example /// /// ```rust /// use aws_smithy_http_server::plugin::plugin_from_operation_id_fn; +/// use aws_smithy_http_server::shape_id::ShapeId; /// use tower::layer::layer_fn; /// /// // A `Service` which prints the operation name before calling `S`. /// struct PrintService { -/// operation_name: &'static str, +/// operation_name: ShapeId, /// inner: S /// } /// /// // A `Layer` applying `PrintService`. /// struct PrintLayer { -/// operation_name: &'static str +/// operation_name: ShapeId /// } /// /// // Defines a closure taking the operation name to `PrintLayer`. diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs b/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs index 2d82aced60..a977db8bf2 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/filter.rs @@ -26,10 +26,11 @@ pub struct FilterByOperationId { /// /// ```rust /// use aws_smithy_http_server::plugin::filter_by_operation_id; +/// use aws_smithy_http_server::shape_id::ShapeId; /// # use aws_smithy_http_server::{plugin::Plugin, operation::{Operation, OperationShape}}; /// # struct Pl; /// # struct CheckHealth; -/// # impl OperationShape for CheckHealth { const NAME: &'static str = ""; type Input = (); type Output = (); type Error = (); } +/// # impl OperationShape for CheckHealth { const NAME: ShapeId = ShapeId::new("ns#CheckHealth", "ns", "CheckHealth"); type Input = (); type Output = (); type Error = (); } /// # impl Plugin<(), CheckHealth, (), ()> for Pl { type Service = (); type Layer = (); fn map(&self, input: Operation<(), ()>) -> Operation<(), ()> { input }} /// # let plugin = Pl; /// # let operation = Operation { inner: (), layer: () }; diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs index c97057f293..19fa4b9d32 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs @@ -12,9 +12,10 @@ //! //! ``` //! # use aws_smithy_http_server::plugin::*; +//! # use aws_smithy_http_server::shape_id::ShapeId; //! # let layer = (); //! # struct GetPokemonSpecies; -//! # impl GetPokemonSpecies { const NAME: &'static str = ""; }; +//! # impl GetPokemonSpecies { const NAME: ShapeId = ShapeId::new("namespace#name", "namespace", "name"); }; //! // Create a `Plugin` from a HTTP `Layer` //! let plugin = HttpLayer(layer); //! @@ -26,9 +27,10 @@ //! //! ``` //! # use aws_smithy_http_server::plugin::*; +//! # use aws_smithy_http_server::shape_id::ShapeId; //! // A `tower::Layer` which requires the operation name //! struct PrintLayer { -//! name: &'static str +//! name: ShapeId, //! } //! //! // Create a `Plugin` using `PrintLayer` @@ -88,7 +90,7 @@ //! /// A [`Layer`] which constructs the [`PrintService`]. //! #[derive(Debug)] //! pub struct PrintLayer { -//! name: &'static str, +//! id: ShapeId, //! } //! impl Layer for PrintLayer { //! type Service = PrintService; @@ -96,7 +98,7 @@ //! fn layer(&self, service: S) -> Self::Service { //! PrintService { //! inner: service, -//! name: self.name, +//! id: self.id.clone(), //! } //! } //! } @@ -113,7 +115,7 @@ //! type Layer = Stack; //! //! fn map(&self, input: Operation) -> Operation { -//! input.layer(PrintLayer { name: Op::NAME }) +//! input.layer(PrintLayer { id: Op::NAME }) //! } //! } //! ``` diff --git a/rust-runtime/aws-smithy-http-server/src/shape_id.rs b/rust-runtime/aws-smithy-http-server/src/shape_id.rs index 860b95dfef..ff887fb4e1 100644 --- a/rust-runtime/aws-smithy-http-server/src/shape_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/shape_id.rs @@ -30,7 +30,7 @@ impl ShapeId { } } - /// Returns the Smithy model namespace. + /// Returns the Smithy operation namespace. pub fn namespace(&self) -> &'static str { self.namespace } From f949f2ee572c5f1a172c17477fe7bd1efa98b32a Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 11 May 2023 14:17:25 +0200 Subject: [PATCH 15/16] fix docs Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/operation/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs index 118e2c125f..d94596b8ad 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs @@ -25,6 +25,7 @@ //! //! ```rust,no_run //! # use aws_smithy_http_server::shape_id::ShapeId; +//! # use aws_smithy_http_server::operation::OperationShape; //! # pub struct CartIdentifier; //! # pub struct ShoppingCart; //! # pub enum GetShoppingError {} From c3ce1e40f9f0bb0ba8dd88c8b3c61b60e0f01c20 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 11 May 2023 15:01:33 +0200 Subject: [PATCH 16/16] Update docs Signed-off-by: Daniele Ahmed --- rust-runtime/aws-smithy-http-server/src/shape_id.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust-runtime/aws-smithy-http-server/src/shape_id.rs b/rust-runtime/aws-smithy-http-server/src/shape_id.rs index ff887fb4e1..1cb13f0921 100644 --- a/rust-runtime/aws-smithy-http-server/src/shape_id.rs +++ b/rust-runtime/aws-smithy-http-server/src/shape_id.rs @@ -7,6 +7,18 @@ //! //! Shape ID is a type that describes a Smithy shape. //! +//! # Example +//! +//! In the following model: +//! ```smithy +//! namespace smithy.example +//! +//! operation CheckHealth {} +//! ``` +//! +//! - `absolute` is `"smithy.example#CheckHealth"` +//! - `namespace` is `"smithy.example"` +//! - `name` is `"CheckHealth"` pub use crate::request::extension::{Extension, MissingExtension};