diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt index 5d1ad0453b1b7ec2119000b3611c0a6b58ecfd1f..332ec5e002f07632230d70985860a9e3690bd8c4 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt @@ -77,10 +77,10 @@ sealed class RustModule { /* Common modules used across client, server and tests */ val Config = public("config", documentation = "Configuration for the service.") - val Error = public("error", documentation = "All error types that operations can return.") - val Model = public("model", documentation = "Data structures used by operation inputs/outputs.") - val Input = public("input", documentation = "Input structures for operations.") - val Output = public("output", documentation = "Output structures for operations.") + val Error = public("error", documentation = "All error types that operations can return. Documentation on these types is copied from the model.") + val Model = public("model", documentation = "Data structures used by operation inputs/outputs. Documentation on these types is copied from the model.") + val Input = public("input", documentation = "Input structures for operations. Documentation on these types is copied from the model.") + val Output = public("output", documentation = "Output structures for operations. Documentation on these types is copied from the model.") val Types = public("types", documentation = "Data primitives referenced by other data types.") /** diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt index 3a3434b8bc37338d08cc71712bb299c4276c7485..768a24073b8862853049755107592cfb855de7ba 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt @@ -171,11 +171,11 @@ open class RustCrate( } } -val ErrorsModule = RustModule.public("error", documentation = "All error types that operations can return.") +val ErrorsModule = RustModule.public("error", documentation = "All error types that operations can return. Documentation on these types is copied from the model.") val OperationsModule = RustModule.public("operation", documentation = "All operations that this crate can perform.") -val ModelsModule = RustModule.public("model", documentation = "Data structures used by operation inputs/outputs.") -val InputsModule = RustModule.public("input", documentation = "Input structures for operations.") -val OutputsModule = RustModule.public("output", documentation = "Output structures for operations.") +val ModelsModule = RustModule.public("model", documentation = "Data structures used by operation inputs/outputs. Documentation on these types is copied from the model.") +val InputsModule = RustModule.public("input", documentation = "Input structures for operations. Documentation on these types is copied from the model.") +val OutputsModule = RustModule.public("output", documentation = "Output structures for operations. Documentation on these types is copied from the model.") val UnconstrainedModule = RustModule.private("unconstrained", "Unconstrained types for constrained shapes.") diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationShapeGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationShapeGenerator.kt index 4f650f19997c2fdc90136bd663beae9c443fed1f..c8bdffe739fa9b523e745781a4bfbc0522d0cca7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationShapeGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationShapeGenerator.kt @@ -30,7 +30,7 @@ class ServerOperationShapeGenerator( writer.rustTemplate( """ - //! A collection of zero-sized types (ZSTs) representing each operation defined in the service closure. + //! A collection of types representing each operation defined in the service closure. //! //! ## Constructing an [`Operation`](#{SmithyHttpServer}::operation::OperationShapeExt) //! @@ -54,8 +54,9 @@ class ServerOperationShapeGenerator( //! //! ## Use as Marker Structs //! - //! The [plugin system](#{SmithyHttpServer}::plugin) also makes use of these ZSTs to parameterize - //! [`Plugin`](#{SmithyHttpServer}::plugin::Plugin) implementations. The traits, such as + //! The [plugin system](#{SmithyHttpServer}::plugin) also makes use of these + //! [zero-sized types](https://doc.rust-lang.org/nomicon/exotic-sizes.html##zero-sized-types-zsts) (ZSTs) to + //! parameterize [`Plugin`](#{SmithyHttpServer}::plugin::Plugin) implementations. The traits, such as //! [`OperationShape`](#{SmithyHttpServer}::operation::OperationShape) can be used to provide //! operation specific information to the [`Layer`](#{Tower}::Layer) being applied. """.trimIndent(), 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 e4082484836029a21d2b457b70770544d6ec93b1..57744a5789de75ae24c3bc0517bf8189e4c97ddc 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 @@ -44,7 +44,7 @@ open class ServerServiceGenerator( fun render() { rustCrate.lib { rust("##[doc(inline, hidden)]") - rust("pub use crate::service::$serviceName;") + rust("pub use crate::service::{$serviceName, ${serviceName}Builder, MissingOperationsError};") } rustCrate.withModule(RustModule.operation(Visibility.PRIVATE)) { @@ -90,7 +90,7 @@ open class ServerServiceGenerator( // TODO(https://github.com/awslabs/smithy-rs/issues/1707): Remove, this is temporary. rustCrate.withModule( - RustModule.LeafModule("service", RustMetadata(visibility = Visibility.PUBLIC, additionalAttributes = listOf(Attribute.DocHidden)), null), + RustModule.LeafModule("service", RustMetadata(visibility = Visibility.PRIVATE, additionalAttributes = listOf(Attribute.DocHidden)), null), ) { ServerServiceGeneratorV2( codegenContext, 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 ff1a76ce14a2d2f754878cb0b410e1be770ba24c..28fcdafd1d6c36319666cf705459b21931674727 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 @@ -346,6 +346,8 @@ class ServerServiceGeneratorV2( rustTemplate( """ + /// + /// See the [root](crate) documentation for more information. ##[derive(Clone)] pub struct $serviceName { router: #{SmithyHttpServer}::routers::RoutingService<#{Router}, #{Protocol}>, @@ -569,11 +571,11 @@ class ServerServiceGeneratorV2( /// /// #### Build /// - /// You can convert [`$builderName`] into [`$serviceName`] using either [`$builderName::build`] or [`$builderName::build_unchecked`]. + /// You can convert [`$builderName`] into [`$serviceName`] using either [`$builderName::build`] or [`$builderName::build_unchecked`]. /// - /// [`$builderName::build`] requires you to provide a handler for every single operation in your Smithy model. It will return an error if that is not the case. + /// [`$builderName::build`] requires you to provide a handler for every single operation in your Smithy model. It will return an error if that is not the case. /// - /// [`$builderName::build_unchecked`], instead, does not require exhaustiveness. The server will automatically return 500s to all requests for operations that do not have a registered handler. + /// [`$builderName::build_unchecked`], instead, does not require exhaustiveness. The server will automatically return 500s to all requests for operations that do not have a registered handler. /// [`$builderName::build_unchecked`] is particularly useful if you are deploying your Smithy service as a collection of Lambda functions, where each Lambda is only responsible for a subset of the operations in the Smithy service (or even a single one!). /// /// ## Example diff --git a/design/src/rfcs/rfc0024_request_id.md b/design/src/rfcs/rfc0024_request_id.md index 5c150ca20039d5e98b28d09b71fd010cc2451a5f..aa25a41f0cc99ebb82a95f44f6ede7fbbdaed235 100644 --- a/design/src/rfcs/rfc0024_request_id.md +++ b/design/src/rfcs/rfc0024_request_id.md @@ -38,7 +38,7 @@ RequestIDs are not to be used by multiple services, but only within a single ser The user experience if this RFC is implemented ---------------------------------------------- -The proposal is to implement a `RequestId` type and make it available to middleware and business logic handlers, through [FromParts](../server/from-parts.md) and as a `Service`. +The proposal is to implement a `RequestId` type and make it available to middleware and business logic handlers, through [FromParts](../server/from_parts.md) and as a `Service`. To aid customers already relying on clients' request IDs, there will be two types: `ClientRequestId` and `ServerRequestId`. 1. Implementing `FromParts` for `Extension` gives customers the ability to write their handlers: diff --git a/design/src/server/anatomy.md b/design/src/server/anatomy.md index 75b577d944947d404ee139c723ee82af0cc8d8ef..794239d3bc27bfcb61da2cf2fc08b15568fa8ab2 100644 --- a/design/src/server/anatomy.md +++ b/design/src/server/anatomy.md @@ -701,6 +701,7 @@ use http::request::Parts; /// Provides a protocol aware extraction from a [`Request`]. This borrows the /// [`Parts`], in contrast to [`FromRequest`]. pub trait FromParts: Sized { + /// The type of the failures yielded extraction attempts. type Rejection: IntoResponse; /// Extracts `self` from a [`Parts`] synchronously. diff --git a/design/src/server/from-parts.md b/design/src/server/from_parts.md similarity index 98% rename from design/src/server/from-parts.md rename to design/src/server/from_parts.md index 695b1bb0abbcbf6195aa40c7ed3a168bc4c61b8c..a03386cc9012c2adf007e76176fc8e130d86234a 100644 --- a/design/src/server/from-parts.md +++ b/design/src/server/from_parts.md @@ -10,6 +10,7 @@ But what if we, the customer, want to access data in the handler which is _not_ /// Provides a protocol aware extraction from a [`Request`]. This borrows the /// [`Parts`], in contrast to [`FromRequest`]. pub trait FromParts: Sized { + /// The type of the failures yielded extraction attempts. type Rejection: IntoResponse; /// Extracts `self` from a [`Parts`] synchronously. diff --git a/design/src/server/overview.md b/design/src/server/overview.md index 7af8b535856f934e8b3aae0a673b1d0d0811dec5..44d177f3f479dbb71b6392d070811dc449f95fa1 100644 --- a/design/src/server/overview.md +++ b/design/src/server/overview.md @@ -7,4 +7,4 @@ Smithy Rust provides the ability to generate a server whose operations are provi - [Instrumentation](./instrumentation.md) - + diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/tests/plugins_execution_order.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/tests/plugins_execution_order.rs index a1852ca11fb91c65a51e064fa154e38e020c8dd1..cc805b375b8854ae01cf92c1821ab759054bc2c1 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/tests/plugins_execution_order.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/tests/plugins_execution_order.rs @@ -36,7 +36,7 @@ async fn plugin_layers_are_executed_in_registration_order() { let pipeline = PluginPipeline::new() .push(SentinelPlugin::new("first", output.clone())) .push(SentinelPlugin::new("second", output.clone())); - let mut app = pokemon_service_server_sdk::service::PokemonService::builder_with_plugins(pipeline) + let mut app = pokemon_service_server_sdk::PokemonService::builder_with_plugins(pipeline) .do_nothing(do_nothing) .build_unchecked(); let request = DoNothingInput::builder() diff --git a/rust-runtime/aws-smithy-http-server/src/body.rs b/rust-runtime/aws-smithy-http-server/src/body.rs index 116903b77231fa919994f52c444e835aeeeb5c30..760e0e3a272f43afb195a83cf96a93bea3d5685c 100644 --- a/rust-runtime/aws-smithy-http-server/src/body.rs +++ b/rust-runtime/aws-smithy-http-server/src/body.rs @@ -15,6 +15,7 @@ use bytes::Bytes; use crate::error::{BoxError, Error}; +/// The primary [`Body`] returned by the generated `smithy-rs` service. pub type BoxBody = http_body::combinators::UnsyncBoxBody; // `boxed` is used in the codegen of the implementation of the operation `Handler` trait. diff --git a/rust-runtime/aws-smithy-http-server/src/extension.rs b/rust-runtime/aws-smithy-http-server/src/extension.rs index 3dfc4fc5d5dc8f336feaa30a59c206818eaa1926..08dbc1c3bfd146b692886a4f5dc03c822eb0e3fc 100644 --- a/rust-runtime/aws-smithy-http-server/src/extension.rs +++ b/rust-runtime/aws-smithy-http-server/src/extension.rs @@ -99,8 +99,7 @@ impl Deref for ModeledErrorExtension { } } -/// Extension type used to store the _name_ of the [`crate::runtime_error::RuntimeError`] that -/// occurred during request handling (see [`crate::runtime_error::RuntimeError::name`]). +/// Extension type used to store the _name_ of the possible runtime errors. /// These are _unmodeled_ errors; the operation handler was not invoked. #[derive(Debug, Clone)] pub struct RuntimeErrorExtension(String); 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 8a809bae8cc211e4ea07e27e0c7edc01b342e99e..72fd2af2e6d090f6e86cc7280ac51b99e60567f4 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs @@ -19,7 +19,7 @@ //! # Ok(Response::new(())) //! # } //! # async fn example() { -//! # let svc = service_fn(service); +//! # let service = service_fn(service); //! let request = Request::get("http://localhost/a/b/c/d?bar=hidden") //! .header("header-name-a", "hidden") //! .body(()) @@ -47,11 +47,11 @@ //! } //! }) //! .status_code(); -//! let mut svc = InstrumentOperation::new(svc, "foo-operation") +//! let mut service = InstrumentOperation::new(service, "foo-operation") //! .request_fmt(request_fmt) //! .response_fmt(response_fmt); //! -//! let _ = svc.call(request).await.unwrap(); +//! let _ = service.call(request).await.unwrap(); //! # } //! ``` //! 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 d358a1e7da1a2b77f2e5804a82ccfb1c74a6f13a..32fabd47cbe3ea69104abcd1c4016dd6c7071659 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/service.rs @@ -101,16 +101,16 @@ where /// # svc.call(Request::new(())); /// ``` #[derive(Debug, Clone)] -pub struct InstrumentOperation { - inner: Svc, +pub struct InstrumentOperation { + inner: S, operation_name: &'static str, make_request: RequestMakeFmt, make_response: ResponseMakeFmt, } -impl InstrumentOperation { +impl InstrumentOperation { /// Constructs a new [`InstrumentOperation`] with no data redacted. - pub fn new(inner: Svc, operation_name: &'static str) -> Self { + pub fn new(inner: S, operation_name: &'static str) -> Self { Self { inner, operation_name, @@ -120,11 +120,11 @@ impl InstrumentOperation { } } -impl InstrumentOperation { +impl InstrumentOperation { /// Configures the request format. /// /// The argument is typically [`RequestFmt`](super::sensitivity::RequestFmt). - pub fn request_fmt(self, make_request: R) -> InstrumentOperation { + pub fn request_fmt(self, make_request: R) -> InstrumentOperation { InstrumentOperation { inner: self.inner, operation_name: self.operation_name, @@ -136,7 +136,7 @@ impl InstrumentOperation(self, make_response: R) -> InstrumentOperation { + pub fn response_fmt(self, make_response: R) -> InstrumentOperation { InstrumentOperation { inner: self.inner, operation_name: self.operation_name, @@ -146,10 +146,10 @@ impl InstrumentOperation Service> - for InstrumentOperation +impl Service> + for InstrumentOperation where - Svc: Service, Response = Response>, + S: Service, Response = Response>, for<'a> RequestMakeFmt: MakeDebug<&'a HeaderMap>, for<'a> RequestMakeFmt: MakeDisplay<&'a Uri>, @@ -158,9 +158,9 @@ where for<'a> ResponseMakeFmt: MakeDebug<&'a HeaderMap>, for<'a> ResponseMakeFmt: MakeDisplay, { - type Response = Svc::Response; - type Error = Svc::Error; - type Future = InstrumentedFuture; + type Response = S::Response; + type Error = S::Error; + type Future = InstrumentedFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) diff --git a/rust-runtime/aws-smithy-http-server/src/macros.rs b/rust-runtime/aws-smithy-http-server/src/macros.rs index 9747c1e33beb0f8b782a76f5d368ee7e9f4967b3..b7df36188d1cae629d243c5e4a932eb6c0c42bc6 100644 --- a/rust-runtime/aws-smithy-http-server/src/macros.rs +++ b/rust-runtime/aws-smithy-http-server/src/macros.rs @@ -35,6 +35,7 @@ //! Macros implementation. /// Define a type that implements [`std::future::Future`]. +#[doc(hidden)] #[macro_export] macro_rules! opaque_future { ($(#[$m:meta])* pub type $name:ident = $actual:ty;) => { diff --git a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs index fc3191f8a0445fcc19f6527323a63b3ea1d20aef..7a30a9a12e188e30838f5f03933983bed983edd0 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs @@ -19,6 +19,8 @@ use tower::Service; use super::{OperationError, OperationShape}; /// A utility trait used to provide an even interface for all operation handlers. +/// +/// See [`operation`](crate::operation) documentation for more info. pub trait Handler where Op: OperationShape, 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 9bcfa1465116057df523acea829d5ce8f9fb6fe5..0aaec2d50fd9e9e36b9be911cffac5a2b92855a5 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs @@ -3,15 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -//! # Operations. -//! //! The shape of a [Smithy operation] is modelled by the [`OperationShape`] trait. Its associated types //! [`OperationShape::Input`], [`OperationShape::Output`], and [`OperationShape::Error`] map to the structures //! representing the Smithy inputs, outputs, and errors respectively. When an operation error is not specified //! [`OperationShape::Error`] is [`Infallible`](std::convert::Infallible). //! -//! We should generate a zero-sized type (ZST) for each Smithy operation and [`OperationShape`] should be implemented -//! on it. This will be used as a helper - providing static methods and parameterizing other traits. +//! We generate a marker struct for each Smithy operation and implement [`OperationShape`] on them. This +//! is used as a helper - providing static methods and parameterizing other traits. //! //! The model //! @@ -41,7 +39,7 @@ //! } //! ``` //! -//! The behavior of a Smithy operation is encoded by an [`Operation`]. The [`OperationShape`] ZSTs can be used to +//! The behavior of a Smithy operation is encoded by an [`Operation`]. The [`OperationShape`] types can be used to //! construct specific operations using [`OperationShapeExt::from_handler`] and [`OperationShapeExt::from_service`]. //! The [from_handler](OperationShapeExt::from_handler) constructor takes a [`Handler`] whereas the //! [from_service](OperationShapeExt::from_service) takes a [`OperationService`]. Both traits serve a similar purpose - @@ -52,7 +50,7 @@ //! The [`Handler`] trait is implemented by all async functions which accept [`OperationShape::Input`] as their first //! argument, the remaining arguments implement [`FromParts`](crate::request::FromParts), and return either //! [`OperationShape::Output`] when [`OperationShape::Error`] is [`Infallible`](std::convert::Infallible) or -//! [`Result`]<[`OperationShape::Output`],[`OperationShape::Error`]>. The following are examples of closures which +//! [`Result`]<[`OperationShape::Output`],[`OperationShape::Error`]>. The following are examples of async functions which //! implement [`Handler`]: //! //! ```rust,no_run diff --git a/rust-runtime/aws-smithy-http-server/src/operation/operation_service.rs b/rust-runtime/aws-smithy-http-server/src/operation/operation_service.rs index 150cd2c65a294350c774b88d8df3db0c6deca00b..2dd7f6d92e1caa257ff78190a4cf9ba484c319ba 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/operation_service.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/operation_service.rs @@ -17,6 +17,8 @@ use super::{OperationError, OperationShape}; /// This serves to take [`Service`]s of the form `Service<(Op::Input, Ext0, Ext1, ...)>` to the canonical /// representation of `Service<(Input, (Ext0, Ext1, ...))>` inline with /// [`IntoService`](super::IntoService). +/// +/// See [`operation`](crate::operation) documentation for more info. pub trait OperationService: Service> where diff --git a/rust-runtime/aws-smithy-http-server/src/operation/upgrade.rs b/rust-runtime/aws-smithy-http-server/src/operation/upgrade.rs index 29fb0fe8e00be4732a396e453242a2b142d8b3b0..cc38466c8cf1944de4aa92e85f2b3b710813ac7b 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/upgrade.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/upgrade.rs @@ -218,6 +218,8 @@ where } /// An interface to convert a representation of a Smithy operation into a [`Route`]. +/// +/// See the [module](crate::operation) documentation for more information. pub trait Upgradable { /// Upgrade the representation of a Smithy operation to a [`Route`]. fn upgrade(self, plugin: &Plugin) -> Route; @@ -271,11 +273,6 @@ where } } -/// A marker struct indicating an [`Operation`] has not been set in a builder. -/// -/// This does _not_ implement [`Upgradable`] purposely. -pub struct MissingOperation; - /// A marker struct indicating an [`Operation`] has not been set in a builder. /// /// This _does_ implement [`Upgradable`] but produces a [`Service`] which always returns an internal failure message. 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 a41faa3c35afdbc445cfc1ad78e895fe4bea74e3..6e43d4b493739847721b25a5292d1c158fad9372 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/mod.rs @@ -49,6 +49,74 @@ //! As noted in the [`PluginPipeline`] documentation, the plugins' runtime logic is executed in registration order, //! meaning that `a` is run _before_ `b` in the example above. //! +//! # Example Implementation +//! +//! ```rust +//! use aws_smithy_http_server::{ +//! operation::{Operation, OperationShape}, +//! plugin::{Plugin, PluginPipeline, PluginStack}, +//! }; +//! # use tower::{layer::util::Stack, Layer, Service}; +//! # use std::task::{Context, Poll}; +//! +//! /// A [`Service`] that adds a print log. +//! #[derive(Clone, Debug)] +//! pub struct PrintService { +//! inner: S, +//! name: &'static str, +//! } +//! +//! impl Service for PrintService +//! 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, req: R) -> Self::Future { +//! println!("Hi {}", self.name); +//! self.inner.call(req) +//! } +//! } +//! +//! /// A [`Layer`] which constructs the [`PrintService`]. +//! #[derive(Debug)] +//! pub struct PrintLayer { +//! name: &'static str, +//! } +//! impl Layer for PrintLayer { +//! type Service = PrintService; +//! +//! fn layer(&self, service: S) -> Self::Service { +//! PrintService { +//! inner: service, +//! name: self.name, +//! } +//! } +//! } +//! +//! /// A [`Plugin`] for a service builder to add a [`PrintLayer`] over operations. +//! #[derive(Debug)] +//! pub struct PrintPlugin; +//! +//! impl Plugin for PrintPlugin +//! where +//! Op: OperationShape, +//! { +//! type Service = S; +//! type Layer = Stack; +//! +//! fn map(&self, input: Operation) -> Operation { +//! input.layer(PrintLayer { name: Op::NAME }) +//! } +//! } +//! ``` +//! mod closure; mod filter; @@ -70,8 +138,12 @@ pub use stack::PluginStack; /// [`Upgradable`](crate::operation::Upgradable) and therefore the resulting service builder. /// /// The generics `Protocol` and `Op` allow the behavior to be parameterized. +/// +/// See [module](crate::plugin) documentation for more information. pub trait Plugin { + /// The type of the new [`Service`](tower::Service). type Service; + /// The type of the new [`Layer`](tower::Layer). type Layer; /// Maps an [`Operation`] to another. diff --git a/rust-runtime/aws-smithy-http-server/src/plugin/stack.rs b/rust-runtime/aws-smithy-http-server/src/plugin/stack.rs index 424a9903711bd3eac8306ac9b675dd76bcef3623..a68e3086d36fed133649db20bc1c21a67f873516 100644 --- a/rust-runtime/aws-smithy-http-server/src/plugin/stack.rs +++ b/rust-runtime/aws-smithy-http-server/src/plugin/stack.rs @@ -10,6 +10,8 @@ use super::Plugin; /// A wrapper struct which composes an `Inner` and an `Outer` [`Plugin`]. /// /// The `Inner::map` is run _then_ the `Outer::map`. +/// +/// Note that the primary tool for composing plugins is [`PluginPipeline`](crate::plugin::PluginPipeline). pub struct PluginStack { inner: Inner, outer: Outer, diff --git a/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs b/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs index ce6b6f1600122d699edc33f378eccfd8fbab3567..9dd1788f82007aae3cee7d9cf56c3c6c8e2adcb6 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs @@ -34,13 +34,16 @@ impl IntoResponse for MissingConnectInfo { } } -/// Extractor for getting connection information produced by a `Connected`. +/// Extractor for getting connection information produced by a [`Connected`](crate::routing::Connected). /// /// Note this extractor requires the existence of [`ConnectInfo`] in the [`http::Extensions`]. This is /// automatically inserted by the [`IntoMakeServiceWithConnectInfo`](crate::routing::IntoMakeServiceWithConnectInfo) /// middleware, which can be applied using the `into_make_service_with_connect_info` method on your generated service. #[derive(Clone, Debug)] -pub struct ConnectInfo(pub T); +pub struct ConnectInfo( + /// The type produced via [`Connected`](crate::routing::Connected). + pub T, +); impl FromParts

for ConnectInfo where 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 77369b871bdb2a4385542fa2666b35e2ab1a884a..7eb6e86baa76747e4e19500d80b42516b4484177 100644 --- a/rust-runtime/aws-smithy-http-server/src/request/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/request/mod.rs @@ -132,9 +132,10 @@ impl RequestParts { } } -// NOTE: We cannot reference `FromRequest` here, as a point of contrast, as it's `doc(hidden)`. -/// Provides a protocol aware extraction from a requests [`Parts`]. +/// Provides a protocol aware extraction from a [`Request`]. This borrows the [`Parts`], in contrast to +/// [`FromRequest`] which consumes the entire [`http::Request`] including the body. pub trait FromParts: Sized { + /// The type of the extraction failures. type Rejection: IntoResponse; /// Extracts `self` from a [`Parts`] synchronously. @@ -187,9 +188,14 @@ impl_from_parts!(Seven, A, B, C, D, E, F, G); impl_from_parts!(Eight, A, B, C, D, E, F, G, H); /// Provides a protocol aware extraction from a [`Request`]. This consumes the -/// [`Request`], in contrast to [`FromParts`]. +/// [`Request`], including the body, in contrast to [`FromParts`] which borrows the [`Parts`]. +/// +/// This should not be implemented by hand. Code generation should implement this for your operations input. To extract +/// items from a HTTP request [`FromParts`] should be used. pub trait FromRequest: Sized { + /// The type of the extraction failures. type Rejection: IntoResponse; + /// The type of the extraction [`Future`]. type Future: Future>; /// Extracts `self` from a [`Request`] asynchronously.