Unverified Commit b84c02bb authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Remove middleware - part 2 (#2925)

This PR continues removing middleware by addressing the simpler
`TODO(enableNewSmithyRuntimeCleanup)` comments in the code generator.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 99ff449b
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ aws-smithy-http-tower = { path = "../../../rust-runtime/aws-smithy-http-tower" }
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] }
aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client"] }
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" }
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" }
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio"] }
aws-types = { path = "../aws-types" }
bytes = "1"
bytes-utils = "0.1.1"
@@ -36,7 +36,6 @@ md-5 = "0.10.1"
ring = "0.16"
tokio = { version = "1.23.1", features = ["full"] }
tokio-stream = "0.1.5"
tower = { version = "0.4", default-features = false }
tracing = "0.1"

[dev-dependencies]
+0 −6
Original line number Diff line number Diff line
@@ -28,9 +28,6 @@ pub mod no_credentials;
/// Support types required for adding presigning to an operation in a generated service.
pub mod presigning;

/// Presigning tower service
pub mod presigning_service;

/// Presigning interceptors
pub mod presigning_interceptors;

@@ -43,9 +40,6 @@ pub mod glacier_checksums;
/// Glacier-specific behavior
pub mod glacier_interceptors;

/// Default middleware stack for AWS services
pub mod middleware;

/// Strip prefixes from IDs returned by Route53 operations when those IDs are used to construct requests
pub mod route53_resource_id_preprocessor_middleware;

+0 −88
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

//! Base Middleware Stack

use aws_endpoint::AwsAuthStage;
use aws_http::auth::CredentialsStage;
use aws_http::recursion_detection::RecursionDetectionStage;
use aws_http::user_agent::UserAgentStage;
use aws_sig_auth::middleware::SigV4SigningStage;
use aws_sig_auth::signer::SigV4Signer;
use aws_smithy_http::endpoint::middleware::SmithyEndpointStage;
use aws_smithy_http_tower::map_request::{AsyncMapRequestLayer, MapRequestLayer};
use std::fmt::Debug;
use tower::ServiceBuilder;

/// Macro to generate the tower stack type. Arguments should be in reverse order
macro_rules! stack_type {
    ($first: ty, $($rest:ty),+) => {
        tower::layer::util::Stack<$first, stack_type!($($rest),+)>
    };
    ($only: ty) => {
        tower::layer::util::Stack<$only, tower::layer::util::Identity>
    }
}

// Note: the layers here appear in reverse order
type DefaultMiddlewareStack = stack_type!(
    MapRequestLayer<RecursionDetectionStage>,
    MapRequestLayer<SigV4SigningStage>,
    AsyncMapRequestLayer<CredentialsStage>,
    MapRequestLayer<UserAgentStage>,
    MapRequestLayer<AwsAuthStage>,
    MapRequestLayer<SmithyEndpointStage>
);

/// AWS Middleware Stack
///
/// This implements the middleware stack for this service. It will:
/// 1. Load credentials asynchronously into the property bag
/// 2. Sign the request with SigV4
/// 3. Resolve an Endpoint for the request
/// 4. Add a user agent to the request
#[derive(Debug, Default, Clone)]
#[non_exhaustive]
pub struct DefaultMiddleware;

impl DefaultMiddleware {
    /// Create a new `DefaultMiddleware` stack
    ///
    /// Note: `DefaultMiddleware` holds no state.
    pub fn new() -> Self {
        DefaultMiddleware::default()
    }
}

// define the middleware stack in a non-generic location to reduce code bloat.
fn base() -> ServiceBuilder<DefaultMiddlewareStack> {
    let credential_provider = AsyncMapRequestLayer::for_mapper(CredentialsStage::new());
    let signer = MapRequestLayer::for_mapper(SigV4SigningStage::new(SigV4Signer::new()));
    let endpoint_stage = MapRequestLayer::for_mapper(SmithyEndpointStage::new());
    let auth_stage = MapRequestLayer::for_mapper(AwsAuthStage);
    let user_agent = MapRequestLayer::for_mapper(UserAgentStage::new());
    let recursion_detection = MapRequestLayer::for_mapper(RecursionDetectionStage::new());
    // These layers can be considered as occurring in order, that is:
    // 1. Resolve an endpoint
    // 2. Add a user agent
    // 3. Acquire credentials
    // 4. Sign with credentials
    // (5. Dispatch over the wire)
    ServiceBuilder::new()
        .layer(endpoint_stage)
        .layer(auth_stage)
        .layer(user_agent)
        .layer(credential_provider)
        .layer(signer)
        .layer(recursion_detection)
}

impl<S> tower::Layer<S> for DefaultMiddleware {
    type Service = <DefaultMiddlewareStack as tower::Layer<S>>::Service;

    fn layer(&self, inner: S) -> Self::Service {
        base().service(inner)
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ impl PresigningConfigBuilder {
pub struct PresignedRequest(http::Request<()>);

impl PresignedRequest {
    #[allow(dead_code)]
    pub(crate) fn new(inner: http::Request<()>) -> Self {
        Self(inner)
    }
+0 −61
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#![allow(dead_code)]

//! Tower middleware service for creating presigned requests

use crate::presigning::PresignedRequest;
use aws_smithy_http::operation;
use http::header::USER_AGENT;
use std::future::{ready, Ready};
use std::marker::PhantomData;
use std::task::{Context, Poll};

/// Tower [`Service`](tower::Service) for generated a [`PresignedRequest`] from the AWS middleware.
#[derive(Default, Debug)]
#[non_exhaustive]
pub(crate) struct PresignedRequestService<E> {
    _phantom: PhantomData<E>,
}

// Required because of the derive Clone on MapRequestService.
// Manually implemented to avoid requiring errors to implement Clone.
impl<E> Clone for PresignedRequestService<E> {
    fn clone(&self) -> Self {
        Self {
            _phantom: Default::default(),
        }
    }
}

impl<E> PresignedRequestService<E> {
    /// Creates a new `PresignedRequestService`
    pub(crate) fn new() -> Self {
        Self {
            _phantom: Default::default(),
        }
    }
}

impl<E> tower::Service<operation::Request> for PresignedRequestService<E> {
    type Response = PresignedRequest;
    type Error = E;
    type Future = Ready<Result<PresignedRequest, E>>;

    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, req: operation::Request) -> Self::Future {
        let (mut req, _) = req.into_parts();

        // Remove user agent headers since the request will not be executed by the AWS Rust SDK.
        req.headers_mut().remove(USER_AGENT);
        req.headers_mut().remove("X-Amz-User-Agent");

        ready(Ok(PresignedRequest::new(req.map(|_| ()))))
    }
}
Loading