Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Http updates #3059

Merged
merged 16 commits into from
Oct 14, 2023
Merged
14 changes: 13 additions & 1 deletion CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Support for Smithy IDLv2 nullability is now enabled by default. You can maintain
For upgrade guidance and more info, see [here](https://github.com/awslabs/smithy-rs/discussions/2929).
"""
references = ["smithy-rs#2916", "smithy-rs#1767"]
meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "client"}
meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "client" }
author = "Velfi"

[[aws-sdk-rust]]
Expand Down Expand Up @@ -378,3 +378,15 @@ message = """Several traits have been renamed from noun form to verb form to be
references = ["smithy-rs#3065"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[smithy-rs]]
message = "**This change has [detailed upgrade guidance](https://github.com/awslabs/smithy-rs/discussions/3067)**. A summary is below.<br><br> The `HttpRequest` type alias now points to `aws-smithy-runtime-api::client::http::Request`. This is a first-party request type to allow us to gracefully support `http = 1.0` when it arrives. Most customer code using this method should be unaffected. `TryFrom`/`TryInto` conversions are provided for `http = 0.2.*`."
references = ["smithy-rs#3059"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "rcoh"

[[aws-sdk-rust]]
message = "[`PresignedRequest`](https://docs.rs/aws-sdk-s3/latest/aws_sdk_s3/presigning/struct.PresignedRequest.html) now returns standard-library types instead of types from the `http` crate. `to_http_request` has been renamed `to_http_02x_request`."
references = ["smithy-rs#3059"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "rcoh"
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ impl Builder {
if let Some(auth) = input.auth {
http_req = http_req.header(AUTHORIZATION, auth);
}
Ok(http_req.body(SdkBody::empty()).expect("valid request"))
Ok(http_req
.body(SdkBody::empty())
.expect("valid request")
.try_into()
.unwrap())
})
.deserializer(move |response| parse_response(provider_name, response))
.build();
Expand Down
19 changes: 14 additions & 5 deletions aws/rust-runtime/aws-config/src/imds/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ use aws_smithy_runtime_api::client::endpoint::{
EndpointFuture, EndpointResolverParams, ResolveEndpoint,
};
use aws_smithy_runtime_api::client::interceptors::context::InterceptorContext;
use aws_smithy_runtime_api::client::orchestrator::{OrchestratorError, SensitiveOutput};
use aws_smithy_runtime_api::client::orchestrator::{
HttpRequest, OrchestratorError, SensitiveOutput,
};
use aws_smithy_runtime_api::client::retries::classifiers::{
ClassifyRetry, RetryAction, SharedRetryClassifier,
};
Expand Down Expand Up @@ -435,10 +437,13 @@ impl Builder {
))
.with_connection_poisoning()
.serializer(|path| {
Ok(http::Request::builder()
.uri(path)
.body(SdkBody::empty())
.expect("valid request"))
Ok(HttpRequest::try_from(
http::Request::builder()
.uri(path)
.body(SdkBody::empty())
.expect("valid request"),
)
.unwrap())
})
.deserializer(|response| {
if response.status().is_success() {
Expand Down Expand Up @@ -626,6 +631,8 @@ pub(crate) mod test {
.method("PUT")
.body(SdkBody::empty())
.unwrap()
.try_into()
.unwrap()
}

pub(crate) fn token_response(ttl: u32, token: &'static str) -> HttpResponse {
Expand All @@ -643,6 +650,8 @@ pub(crate) mod test {
.header("x-aws-ec2-metadata-token", token)
.body(SdkBody::empty())
.unwrap()
.try_into()
.unwrap()
}

pub(crate) fn imds_response(body: &'static str) -> HttpResponse {
Expand Down
4 changes: 3 additions & 1 deletion aws/rust-runtime/aws-config/src/imds/client/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ impl TokenResolver {
.uri(Uri::from_static("/latest/api/token"))
.header(X_AWS_EC2_METADATA_TOKEN_TTL_SECONDS, token_ttl.as_secs())
.body(SdkBody::empty())
.expect("valid HTTP request"))
.expect("valid HTTP request")
.try_into()
.unwrap())
})
.deserializer({
let time_source = time_source.clone();
Expand Down
12 changes: 3 additions & 9 deletions aws/rust-runtime/aws-config/src/sts/assume_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ mod test {
let req = request.expect_request();
let str_body = std::str::from_utf8(req.body().bytes().unwrap()).unwrap();
assert!(str_body.contains("1234567"), "{}", str_body);
assert_eq!(req.uri(), "https://sts.us-east-1.amazonaws.com");
assert_eq!(req.uri(), "https://sts.us-east-1.amazonaws.com/");
}

#[tokio::test]
Expand Down Expand Up @@ -411,7 +411,7 @@ mod test {
.await;
let _ = dbg!(provider.provide_credentials().await);
let req = request.expect_request();
assert_eq!(req.uri(), "https://sts.us-west-2.amazonaws.com");
assert_eq!(req.uri(), "https://sts.us-west-2.amazonaws.com/");
}

/// Test that `build()` where no provider is passed still works
Expand Down Expand Up @@ -442,13 +442,7 @@ mod test {
.await;
let _ = provider.provide_credentials().await;
let req = request.expect_request();
let auth_header = req
.headers()
.get(AUTHORIZATION)
.unwrap()
.to_str()
.unwrap()
.to_string();
let auth_header = req.headers().get(AUTHORIZATION).unwrap().to_string();
let expect = "Credential=123-key/20090213/us-west-17/sts/aws4_request";
assert!(
auth_header.contains(expect),
Expand Down
1 change: 1 addition & 0 deletions aws/rust-runtime/aws-inlineable/external-types.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
allowed_external_types = [
"aws_credential_types::provider::ProvideCredentials",
"aws_smithy_http::*",
"aws_smithy_runtime_api::*",

"http::error::Error",
"http::header::map::HeaderMap",
Expand Down
44 changes: 20 additions & 24 deletions aws/rust-runtime/aws-inlineable/src/glacier_interceptors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
// This code is referenced in generated code, so the compiler doesn't realize it is used.
#![allow(dead_code)]

use std::fmt;
use std::marker::PhantomData;

use bytes::Bytes;
use http::header::HeaderValue;
use ring::digest::{Context, Digest, SHA256};

use aws_runtime::auth::SigV4OperationSigningConfig;
use aws_sigv4::http_request::SignableBody;
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::byte_stream;
use aws_smithy_runtime_api::box_error::BoxError;
use aws_smithy_runtime_api::client::interceptors::context::{
BeforeSerializationInterceptorContextMut, BeforeTransmitInterceptorContextMut,
};
use aws_smithy_runtime_api::client::interceptors::Intercept;
use aws_smithy_runtime_api::client::orchestrator::LoadedRequestBody;

use aws_smithy_runtime_api::client::orchestrator::{HttpRequest, LoadedRequestBody};
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
use aws_smithy_types::config_bag::ConfigBag;
use bytes::Bytes;
use http::header::{HeaderName, HeaderValue};
use http::Request;
use ring::digest::{Context, Digest, SHA256};
use std::fmt;
use std::marker::PhantomData;

/// The default account ID when none is set on an input
const DEFAULT_ACCOUNT_ID: &str = "-";
Expand Down Expand Up @@ -182,23 +183,19 @@ impl Intercept for GlacierTreeHashHeaderInterceptor {
///
/// See <https://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html> for more information.
fn add_checksum_treehash(
request: &mut Request<SdkBody>,
request: &mut HttpRequest,
body: &Bytes,
) -> Result<String, byte_stream::error::Error> {
let (full_body, hashes) = compute_hashes(body, MEGABYTE)?;
let tree_hash = hex::encode(compute_hash_tree(hashes));
let complete_hash = hex::encode(full_body);
if !request.headers().contains_key(TREE_HASH_HEADER) {
request.headers_mut().insert(
HeaderName::from_static(TREE_HASH_HEADER),
tree_hash.parse().expect("hash must be valid header"),
);
request.headers_mut().insert(TREE_HASH_HEADER, tree_hash);
}
if !request.headers().contains_key(X_AMZ_CONTENT_SHA256) {
request.headers_mut().insert(
HeaderName::from_static(X_AMZ_CONTENT_SHA256),
complete_hash.parse().expect("hash must be valid header"),
);
request
.headers_mut()
.insert(X_AMZ_CONTENT_SHA256, complete_hash.clone());
}
Ok(complete_hash)
}
Expand Down Expand Up @@ -251,10 +248,11 @@ fn compute_hash_tree(mut hashes: Vec<Digest>) -> Digest {

#[cfg(test)]
mod account_id_autofill_tests {
use super::*;
use aws_smithy_runtime_api::client::interceptors::context::{Input, InterceptorContext};
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;

use super::*;

#[test]
fn autofill_account_id() {
#[derive(Debug)]
Expand Down Expand Up @@ -290,16 +288,17 @@ mod account_id_autofill_tests {

#[cfg(test)]
mod api_version_tests {
use super::*;
use aws_smithy_runtime_api::client::interceptors::context::{Input, InterceptorContext};
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;

use super::*;

#[test]
fn api_version_interceptor() {
let rc = RuntimeComponentsBuilder::for_tests().build().unwrap();
let mut cfg = ConfigBag::base();
let mut context = InterceptorContext::new(Input::doesnt_matter());
context.set_request(http::Request::builder().body(SdkBody::empty()).unwrap());
context.set_request(HttpRequest::empty());
let mut context = BeforeTransmitInterceptorContextMut::from(&mut context);

let interceptor = GlacierApiVersionInterceptor::new("some-version");
Expand Down Expand Up @@ -393,10 +392,7 @@ mod treehash_checksum_tests {
}
let test_data = Bytes::from(test_data);

let mut http_req = http::Request::builder()
.uri("http://example.com/hello")
.body(SdkBody::taken()) // the body isn't used by add_checksum_treehash
.unwrap();
let mut http_req = HttpRequest::empty();

add_checksum_treehash(&mut http_req, &test_data).expect("should succeed");
// hash value verified with AWS CLI
Expand Down
34 changes: 18 additions & 16 deletions aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use aws_smithy_runtime_api::client::interceptors::context::{
BeforeSerializationInterceptorContextRef, BeforeTransmitInterceptorContextMut, Input,
};
use aws_smithy_runtime_api::client::interceptors::Intercept;

use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
use aws_smithy_types::config_bag::{ConfigBag, Layer, Storable, StoreReplace};
use http::HeaderValue;
Expand Down Expand Up @@ -121,7 +123,7 @@ where
}

fn add_checksum_for_request_body(
request: &mut http::request::Request<SdkBody>,
request: &mut HttpRequest,
checksum_algorithm: ChecksumAlgorithm,
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
Expand Down Expand Up @@ -151,7 +153,7 @@ fn add_checksum_for_request_body(
}

fn wrap_streaming_request_body_in_checksum_calculating_body(
request: &mut http::request::Request<SdkBody>,
request: &mut HttpRequest,
checksum_algorithm: ChecksumAlgorithm,
) -> Result<(), BuildError> {
let original_body_size = request
Expand Down Expand Up @@ -185,8 +187,7 @@ fn wrap_streaming_request_body_in_checksum_calculating_body(

headers.insert(
http::header::HeaderName::from_static("x-amz-trailer"),
// Convert into a `HeaderName` and then into a `HeaderValue`
http::header::HeaderName::from(checksum_algorithm).into(),
checksum_algorithm.into_impl().header_name(),
);

headers.insert(
Expand Down Expand Up @@ -215,6 +216,7 @@ mod tests {
use aws_smithy_checksums::ChecksumAlgorithm;
use aws_smithy_http::body::SdkBody;
use aws_smithy_http::byte_stream::ByteStream;
use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
use aws_smithy_types::base64;
use bytes::BytesMut;
use http_body::Body;
Expand All @@ -224,8 +226,10 @@ mod tests {
async fn test_checksum_body_is_retryable() {
let input_text = "Hello world";
let chunk_len_hex = format!("{:X}", input_text.len());
let mut request = http::Request::builder()
let mut request: HttpRequest = http::Request::builder()
.body(SdkBody::retryable(move || SdkBody::from(input_text)))
.unwrap()
.try_into()
.unwrap();

// ensure original SdkBody is retryable
Expand Down Expand Up @@ -265,17 +269,15 @@ mod tests {
}
let crc32c_checksum = crc32c_checksum.finalize();

let mut request = http::Request::builder()
.body(
ByteStream::read_from()
.path(&file)
.buffer_size(1024)
.build()
.await
.unwrap()
.into_inner(),
)
.unwrap();
let mut request = HttpRequest::new(
ByteStream::read_from()
.path(&file)
.buffer_size(1024)
.build()
.await
.unwrap()
.into_inner(),
);

// ensure original SdkBody is retryable
assert!(request.body().try_clone().is_some());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ pub(crate) fn check_headers_for_precalculated_checksum(
"CHECKSUM_ALGORITHMS_IN_PRIORITY_ORDER only contains valid checksum algorithm names",
);
if let Some(precalculated_checksum) =
headers.get(http::HeaderName::from(checksum_algorithm))
headers.get(checksum_algorithm.into_impl().header_name())
{
let base64_encoded_precalculated_checksum = precalculated_checksum
.to_str()
Expand Down
Loading
Loading