RFC: Service-specific middleware
Status: Implemented
For a summarized list of proposed changes, see the Changes Checklist section.
Currently, all services use a centralized AwsMiddleware that is defined in the (poorly named) aws-hyper crate. This
poses a number of long term risks and limitations:
- When creating a Smithy Client directly for a given service, customers are forced to implicitly assume that the
service uses stock
AwsMiddleware. This prevents us from ever changing the middleware stack for a service in the future. - It is impossible / impractical in the current situation to alter the middleware stack for a given service. For services like S3, we will almost certainly want to customize endpoint middleware in a way that is currently impossible.
In light of these limitations, this RFC proposes moving middleware into each generated service. aws-inlineable will be
used to host and test the middleware stack. Each service will then define a public middleware module containing their
middleware stack.
Terminology
- Middleware: A tower layer that augments
operation::Request -> operation::Responsefor things like signing and endpoint resolution. - Aws Middleware: A specific middleware stack that meets the requirements for AWS services.
- Smithy Client: A
aws_smithy_client::Client<C, M, R>struct that is responsible for gluing together the connector, middleware, and retry policy. This is not generated and lives in theaws-smithy-clientcrate. - Fluent Client: A code-generated
Client<C, M, R>that has methods for each service operation on it. A fluent builder is generated alongside it to make construction easier. - AWS Client: A specialized Fluent Client that defaults to using a
DynConnector,AwsMiddleware, andStandardretry policy. - Shared Config: An
aws_types::Configstruct that is responsible for storing shared configuration data that is used across all services. This is not generated and lives in theaws-typescrate. - Service-specific Config: A code-generated
Configthat has methods for setting service-specific configuration. EachConfigis defined in theconfigmodule of its parent service. For example, the S3-specific config struct isuseable fromaws_sdk_s3::config::Configand re-exported asaws_sdk_s3::Config.
Detailed Design
Currently, AwsMiddleware is defined in aws-hyper. As part of this change, an aws-inlineable dependency will be
added containing code that is largely identical. This will be exposed in a public middleware module in all generated
services. At some future point, we could even expose a baseline set of default middleware for whitelabel Smithy services
to make them easier to use out-of-the-box.
The ClientGenerics parameter of the AwsFluentClientGenerator will be updated to become a RuntimeType, enabling
loading the type directly. This has the advantage of making it fairly easy to do per-service middleware stacks since we
can easily configure AwsFluentClientGenerator to insert different types based on the service id.
Changes Checklist
- Move aws-hyper into aws-inlineable. Update comments as needed including with a usage example about how customers can augment it.
-
Refactor
ClientGenericsto contain a RuntimeType instead of a string and configure. UpdateAwsFluentClientDecorator. -
Update all code and examples that use
aws-hyperto use service-specific middleware. - Push an updated README to aws-hyper deprecating the package, explaining what happened. Do not yank previous versions since those will be relied on by older SDK versions.