Unverified Commit 118151e2 authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Add Clone impl to PresignedRequest (#3084)

## Motivation and Context
This makes it easier to convert presigned request into an HTTP request

## Description
<!--- Describe your changes in detail -->
- add clone impl
- add `make_presigned_request` that borrows from self

## Testing
CI
## Checklist
<!--- If a checkbox below is not applicable, then please DELETE it
rather than leaving it unchecked -->
- [ ] I have updated `CHANGELOG.next.toml` if I made changes to the
smithy-rs codegen or runtime crates
- [ ] I have updated `CHANGELOG.next.toml` if I made changes to the AWS
SDK, generated SDK code, or SDK runtime crates

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 6ceabf8b
Loading
Loading
Loading
Loading
+45 −11
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

use aws_smithy_runtime_api::box_error::BoxError;
use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
use aws_smithy_types::body::SdkBody;
use std::fmt;
use std::time::{Duration, SystemTime};

@@ -170,37 +171,70 @@ impl PresigningConfigBuilder {
///
/// **This struct has conversion convenience functions:**
///
/// - [`PresignedRequest::to_http_02x_request<B>`][Self::to_http_02x_request] returns an [`http::Request<B>`](https://docs.rs/http/0.2.6/http/request/struct.Request.html)
/// - [`PresignedRequest::make_http_02x_request<B>`][Self::make_http_02x_request] returns an [`http::Request<B>`](https://docs.rs/http/0.2.6/http/request/struct.Request.html)
/// - [`PresignedRequest::into`](#impl-From<PresignedRequest>) returns an [`http::request::Builder`](https://docs.rs/http/0.2.6/http/request/struct.Builder.html)
#[non_exhaustive]
pub struct PresignedRequest(HttpRequest);
pub struct PresignedRequest {
    http_request: HttpRequest,
}

impl Clone for PresignedRequest {
    fn clone(&self) -> Self {
        Self {
            http_request: match self.http_request.try_clone() {
                Some(body) => body,
                None => {
                    unreachable!(
                        "during construction, we replaced the body with `SdkBody::empty()`"
                    )
                }
            },
        }
    }
}

impl PresignedRequest {
    #[allow(dead_code)]
    pub(crate) fn new(inner: HttpRequest) -> Self {
        Self(inner)
    pub(crate) fn new(inner: HttpRequest) -> Result<Self, BoxError> {
        // throw out the body so we're sure it's cloneable
        let http_request = inner.map(|_body| SdkBody::empty());
        // this should never fail, a presigned request should always be convertible, but better to
        // protect against this potential panic
        let _ = http_request
            .try_clone()
            .expect("must be cloneable, body is empty")
            .into_http02x()?;
        Ok(Self { http_request })
    }

    /// Returns the HTTP request method.
    pub fn method(&self) -> &str {
        self.0.method()
        self.http_request.method()
    }

    /// Returns the HTTP request URI.
    pub fn uri(&self) -> &str {
        self.0.uri()
        self.http_request.uri()
    }

    /// Returns any HTTP headers that need to go along with the request, except for `Host`,
    /// which should be sent based on the endpoint in the URI by the HTTP client rather than
    /// added directly.
    pub fn headers(&self) -> impl Iterator<Item = (&str, &str)> {
        self.0.headers().iter()
        self.http_request.headers().iter()
    }

    /// Given a body, produce an `http::Request` from this `PresignedRequest`
    pub fn make_http_02x_request<B>(&self, body: B) -> http::Request<B> {
        self.clone().into_http_02x_request(body)
    }

    /// Given a body, convert this `PresignedRequest` into an `http::Request`
    pub fn to_http_02x_request<B>(self, body: B) -> Result<http::Request<B>, BoxError> {
        Ok(self.0.into_http02x()?.map(|_req| body))
    /// Converts this `PresignedRequest` directly into an `http` request.
    pub fn into_http_02x_request<B>(self, body: B) -> http::Request<B> {
        self.http_request
            .into_http02x()
            .expect("constructor validated convertibility")
            .map(|_req| body)
    }
}

@@ -209,7 +243,7 @@ impl fmt::Debug for PresignedRequest {
        f.debug_struct("PresignedRequest")
            .field("method", &self.method())
            .field("uri", &self.uri())
            .field("headers", self.0.headers())
            .field("headers", self.http_request.headers())
            .finish()
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ class AwsPresignedFluentBuilderMethod(
                    })
                })?;
            let request = context.take_request().expect("request set before transmit");
            Ok(#{PresignedRequest}::new(request))
            #{PresignedRequest}::new(request).map_err(#{SdkError}::construction_failure)
            """,
            *codegenScope,
            "Operation" to codegenContext.symbolProvider.toSymbol(section.operationShape),