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

Feature: Request Compression for operations modeled with the @requestCompression trait #3647

Merged
merged 13 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,23 @@ message = "Updating the documentation for the `app_name` method on `ConfigLoader
references = ["smithy-rs#3645"]
meta = { "breaking" = false, "bug" = false, "tada" = false }
author = "landonxjames"

[[smithy-rs]]
message = """
Compression is now supported for operations modeled with the `@requestCompression` trait.

[**For more details, see the long-form changelog discussion**](https://github.com/smithy-lang/smithy-rs/discussions/3646).
"""
references = ["smithy-rs#2891"]
meta = { "breaking" = false, "bug" = false, "tada" = true, "target" = "client" }
author = "Velfi"

[[aws-sdk-rust]]
message = """
Compression is now supported for operations modeled with the `@requestCompression` trait.

[**For more details, see the long-form changelog discussion**](https://github.com/smithy-lang/smithy-rs/discussions/3646).
"""
references = ["smithy-rs#2891"]
meta = { "breaking" = false, "bug" = false, "tada" = true }
author = "Velfi"
9 changes: 4 additions & 5 deletions aws/rust-runtime/aws-config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aws-config"
version = "1.4.1"
version = "1.5.0"
authors = [
"AWS Rust SDK Team <aws-sdk-rust@amazon.com>",
"Russell Cohen <rcoh@amazon.com>",
Expand All @@ -14,12 +14,11 @@ repository = "https://github.com/smithy-lang/smithy-rs"
[features]
behavior-version-latest = []
client-hyper = ["aws-smithy-runtime/connector-hyper-0-14-x"]
rustls = ["aws-smithy-runtime/tls-rustls", "client-hyper"]
rt-tokio = ["aws-smithy-async/rt-tokio", "aws-smithy-runtime/rt-tokio", "tokio/rt"]
sso = ["dep:aws-sdk-sso", "dep:aws-sdk-ssooidc", "dep:ring", "dep:hex", "dep:zeroize", "aws-smithy-runtime-api/http-auth"]
credentials-process = ["tokio/process"]

default = ["client-hyper", "rustls", "rt-tokio", "credentials-process", "sso"]
rt-tokio = ["aws-smithy-async/rt-tokio", "aws-smithy-runtime/rt-tokio", "tokio/rt"]
rustls = ["aws-smithy-runtime/tls-rustls", "client-hyper"]
sso = ["dep:aws-sdk-sso", "dep:aws-sdk-ssooidc", "dep:ring", "dep:hex", "dep:zeroize", "aws-smithy-runtime-api/http-auth"]

# deprecated: this feature does nothing
allow-compilation = []
Expand Down
6 changes: 6 additions & 0 deletions aws/rust-runtime/aws-config/src/default_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ pub mod ignore_configured_endpoint_urls;

/// Default endpoint URL provider chain
pub mod endpoint_url;

/// Default "disable request compression" provider chain
pub mod disable_request_compression;

/// Default "request minimum compression size bytes" provider chain
pub mod request_min_compression_size_bytes;
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use crate::environment::parse_bool;
use crate::provider_config::ProviderConfig;
use aws_runtime::env_config::EnvConfigValue;
use aws_smithy_types::error::display::DisplayErrorContext;

mod env {
pub(super) const DISABLE_REQUEST_COMPRESSION: &str = "AWS_DISABLE_REQUEST_COMPRESSION";
}

mod profile_key {
pub(super) const DISABLE_REQUEST_COMPRESSION: &str = "disable_request_compression";
}

/// Load the value for "disable request compression".
///
/// This checks the following sources:
/// 1. The environment variable `AWS_DISABLE_REQUEST_COMPRESSION=true/false`
/// 2. The profile key `disable_request_compression=true/false`
///
/// If invalid values are found, the provider will return None and an error will be logged.
pub(crate) async fn disable_request_compression_provider(
provider_config: &ProviderConfig,
) -> Option<bool> {
let env = provider_config.env();
let profiles = provider_config.profile().await;

EnvConfigValue::new()
.env(env::DISABLE_REQUEST_COMPRESSION)
.profile(profile_key::DISABLE_REQUEST_COMPRESSION)
.validate(&env, profiles, parse_bool)
.map_err(
|err| tracing::warn!(err = %DisplayErrorContext(&err), "invalid value for `disable request compression` setting"),
)
.unwrap_or(None)
}

#[cfg(test)]
mod test {
use super::disable_request_compression_provider;
#[allow(deprecated)]
use crate::profile::profile_file::{ProfileFileKind, ProfileFiles};
use crate::provider_config::ProviderConfig;
use aws_types::os_shim_internal::{Env, Fs};
use tracing_test::traced_test;

#[tokio::test]
#[traced_test]
async fn log_error_on_invalid_value() {
let conf = ProviderConfig::empty().with_env(Env::from_slice(&[(
"AWS_DISABLE_REQUEST_COMPRESSION",
"not-a-boolean",
)]));
assert_eq!(disable_request_compression_provider(&conf).await, None);
assert!(logs_contain(
"invalid value for `disable request compression` setting"
));
assert!(logs_contain("AWS_DISABLE_REQUEST_COMPRESSION"));
}

#[tokio::test]
#[traced_test]
async fn environment_priority() {
let conf = ProviderConfig::empty()
.with_env(Env::from_slice(&[(
"AWS_DISABLE_REQUEST_COMPRESSION",
"TRUE",
)]))
.with_profile_config(
Some(
#[allow(deprecated)]
ProfileFiles::builder()
.with_file(
#[allow(deprecated)]
ProfileFileKind::Config,
"conf",
)
.build(),
),
None,
)
.with_fs(Fs::from_slice(&[(
"conf",
"[default]\ndisable_request_compression = false",
)]));
assert_eq!(
disable_request_compression_provider(&conf).await,
Some(true)
);
}

#[tokio::test]
#[traced_test]
async fn profile_config_works() {
let conf = ProviderConfig::empty()
.with_profile_config(
Some(
#[allow(deprecated)]
ProfileFiles::builder()
.with_file(
#[allow(deprecated)]
ProfileFileKind::Config,
"conf",
)
.build(),
),
None,
)
.with_fs(Fs::from_slice(&[(
"conf",
"[default]\ndisable_request_compression = true",
)]));
assert_eq!(
disable_request_compression_provider(&conf).await,
Some(true)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use crate::environment::parse_uint;
use crate::provider_config::ProviderConfig;
use aws_runtime::env_config::EnvConfigValue;
use aws_smithy_types::error::display::DisplayErrorContext;

mod env {
pub(super) const REQUEST_MIN_COMPRESSION_SIZE_BYTES: &str =
"AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES";
}

mod profile_key {
pub(super) const REQUEST_MIN_COMPRESSION_SIZE_BYTES: &str =
"request_min_compression_size_bytes";
}

/// Load the value for "request minimum compression size bytes".
///
/// This checks the following sources:
/// 1. The environment variable `AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES=10240`
/// 2. The profile key `request_min_compression_size_bytes=10240`
///
/// If invalid values are found, the provider will return None and an error will be logged.
pub(crate) async fn request_min_compression_size_bytes_provider(
provider_config: &ProviderConfig,
) -> Option<u32> {
let env = provider_config.env();
let profiles = provider_config.profile().await;

EnvConfigValue::new()
.env(env::REQUEST_MIN_COMPRESSION_SIZE_BYTES)
.profile(profile_key::REQUEST_MIN_COMPRESSION_SIZE_BYTES)
.validate(&env, profiles, parse_uint)
.map_err(
|err| tracing::warn!(err = %DisplayErrorContext(&err), "invalid value for `request minimum compression size bytes` setting"),
)
.unwrap_or(None)
}

#[cfg(test)]
mod test {
use super::request_min_compression_size_bytes_provider;
#[allow(deprecated)]
use crate::profile::profile_file::{ProfileFileKind, ProfileFiles};
use crate::provider_config::ProviderConfig;
use aws_types::os_shim_internal::{Env, Fs};
use tracing_test::traced_test;

#[tokio::test]
#[traced_test]
async fn log_error_on_invalid_value() {
let conf = ProviderConfig::empty().with_env(Env::from_slice(&[(
"AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES",
"not-a-uint",
)]));
assert_eq!(
request_min_compression_size_bytes_provider(&conf).await,
None
);
assert!(logs_contain(
"invalid value for `request minimum compression size bytes` setting"
));
assert!(logs_contain("AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES"));
}

#[tokio::test]
#[traced_test]
async fn environment_priority() {
let conf = ProviderConfig::empty()
.with_env(Env::from_slice(&[(
"AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES",
"99",
)]))
.with_profile_config(
Some(
#[allow(deprecated)]
ProfileFiles::builder()
.with_file(
#[allow(deprecated)]
ProfileFileKind::Config,
"conf",
)
.build(),
),
None,
)
.with_fs(Fs::from_slice(&[(
"conf",
"[default]\nrequest_min_compression_size_bytes = 100",
)]));
assert_eq!(
request_min_compression_size_bytes_provider(&conf).await,
Some(99)
);
}

#[tokio::test]
#[traced_test]
async fn profile_config_works() {
let conf = ProviderConfig::empty()
.with_profile_config(
Some(
#[allow(deprecated)]
ProfileFiles::builder()
.with_file(
#[allow(deprecated)]
ProfileFileKind::Config,
"conf",
)
.build(),
),
None,
)
.with_fs(Fs::from_slice(&[(
"conf",
"[default]\nrequest_min_compression_size_bytes = 22",
)]));
assert_eq!(
request_min_compression_size_bytes_provider(&conf).await,
Some(22)
);
}
}
19 changes: 19 additions & 0 deletions aws/rust-runtime/aws-config/src/environment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ pub(crate) fn parse_bool(value: &str) -> Result<bool, InvalidBooleanValue> {
}
}

#[derive(Debug)]
pub(crate) struct InvalidUintValue {
value: String,
}

impl fmt::Display for InvalidUintValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} is not a valid u32", self.value)
}
}

impl Error for InvalidUintValue {}

pub(crate) fn parse_uint(value: &str) -> Result<u32, InvalidUintValue> {
value.parse::<u32>().map_err(|_| InvalidUintValue {
value: value.to_string(),
})
}

#[derive(Debug)]
pub(crate) struct InvalidUrlValue {
value: String,
Expand Down
Loading
Loading