Skip to content

Commit

Permalink
Move response mutator to closure
Browse files Browse the repository at this point in the history
  • Loading branch information
landonxjames committed Sep 30, 2024
1 parent d682c8d commit 6c9c3da
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 196 deletions.
19 changes: 12 additions & 7 deletions aws/rust-runtime/aws-inlineable/src/http_response_checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use aws_smithy_checksums::ChecksumAlgorithm;
use aws_smithy_runtime_api::box_error::BoxError;
use aws_smithy_runtime_api::client::interceptors::context::{
BeforeDeserializationInterceptorContextMut, BeforeSerializationInterceptorContextRef, Input,
BeforeDeserializationInterceptorContextMut, BeforeSerializationInterceptorContextMut, Input,
};
use aws_smithy_runtime_api::client::interceptors::Intercept;
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
Expand All @@ -28,45 +28,50 @@ impl Storable for ResponseChecksumInterceptorState {
type Storer = StoreReplace<Self>;
}

pub(crate) struct ResponseChecksumInterceptor<VE> {
pub(crate) struct ResponseChecksumInterceptor<VE, CM> {
response_algorithms: &'static [&'static str],
validation_enabled: VE,
checksum_mutator: CM,
}

impl<VE> fmt::Debug for ResponseChecksumInterceptor<VE> {
impl<VE, CM> fmt::Debug for ResponseChecksumInterceptor<VE, CM> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ResponseChecksumInterceptor")
.field("response_algorithms", &self.response_algorithms)
.finish()
}
}

impl<VE> ResponseChecksumInterceptor<VE> {
impl<VE, CM> ResponseChecksumInterceptor<VE, CM> {
pub(crate) fn new(
response_algorithms: &'static [&'static str],
validation_enabled: VE,
checksum_mutator: CM,
) -> Self {
Self {
response_algorithms,
validation_enabled,
checksum_mutator,
}
}
}

impl<VE> Intercept for ResponseChecksumInterceptor<VE>
impl<VE, CM> Intercept for ResponseChecksumInterceptor<VE, CM>
where
VE: Fn(&Input) -> bool + Send + Sync,
CM: Fn(&mut Input, &ConfigBag) -> Result<(), BoxError> + Send + Sync,
{
fn name(&self) -> &'static str {
"ResponseChecksumInterceptor"
}

fn read_before_serialization(
fn modify_before_serialization(
&self,
context: &BeforeSerializationInterceptorContextRef<'_>,
context: &mut BeforeSerializationInterceptorContextMut<'_>,
_runtime_components: &RuntimeComponents,
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
let _ = (self.checksum_mutator)(context.input_mut(), cfg);
let validation_enabled = (self.validation_enabled)(context.input());

let mut layer = Layer::new("ResponseChecksumInterceptor");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ val DECORATORS: List<ClientCodegenDecorator> =
SigV4AuthDecorator(),
HttpRequestChecksumDecorator(),
HttpResponseChecksumDecorator(),
HttpResponseChecksumMutationInterceptorDecorator(),
IntegrationTestDecorator(),
AwsFluentClientDecorator(),
CrateLicenseDecorator(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package software.amazon.smithy.rustsdk

import software.amazon.smithy.aws.traits.HttpChecksumTrait
import software.amazon.smithy.model.knowledge.TopDownIndex
import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.configReexport
Expand Down Expand Up @@ -347,3 +348,15 @@ fun serviceHasHttpChecksumOperation(codegenContext: ClientCodegenContext): Boole
val ops = index.getContainedOperations(codegenContext.serviceShape.id)
return ops.any { it.hasTrait<HttpChecksumTrait>() }
}

/**
* Get the top-level operation input member used to opt-in to best-effort validation of a checksum returned in
* the HTTP response of the operation.
*/
fun HttpChecksumTrait.requestAlgorithmMemberShape(
codegenContext: ClientCodegenContext,
operationShape: OperationShape,
): MemberShape? {
val requestAlgorithmMember = this.requestAlgorithmMember.orNull() ?: return null
return operationShape.inputShape(codegenContext.model).expectMember(requestAlgorithmMember)
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class HttpResponseChecksumCustomization(
val checksumTrait = operationShape.getTrait<HttpChecksumTrait>() ?: return@writable
val requestValidationModeMember =
checksumTrait.requestValidationModeMember(codegenContext, operationShape) ?: return@writable
val requestValidationModeName = codegenContext.symbolProvider.toSymbol(requestValidationModeMember).name
val requestValidationModeMemberInner =
if (requestValidationModeMember.isOptional) {
codegenContext.model.expectShape(requestValidationModeMember.target)
Expand Down Expand Up @@ -150,6 +151,34 @@ class HttpResponseChecksumCustomization(
}
let input: &#{OperationInput} = input.downcast_ref().expect("correct type");
matches!(input.$validationModeName(), #{Some}(#{ValidationModeShape}::Enabled))
},
|input: &mut #{Input}, cfg: &#{ConfigBag}| {
let input = input
.downcast_mut::<#{OperationInputType}>()
.ok_or("failed to downcast to #{OperationInputType}")?;
let request_validation_enabled =
matches!(input.$requestValidationModeName(), Some(#{ValidationModeShape}::Enabled));
if !request_validation_enabled {
// This value is set by the user on the SdkConfig to indicate their preference
let response_checksum_validation = cfg
.load::<#{ResponseChecksumValidation}>()
.unwrap_or(&#{ResponseChecksumValidation}::WhenSupported);
// If validation setting is WhenSupported (or unknown) we enable response checksum
// validation. If it is WhenRequired we do not enable (since there is no way to
// indicate that a response checksum is required).
##[allow(clippy::wildcard_in_or_patterns)]
match response_checksum_validation {
#{ResponseChecksumValidation}::WhenRequired => {}
#{ResponseChecksumValidation}::WhenSupported | _ => {
input.$requestValidationModeName = Some(#{ValidationModeShape}::Enabled);
}
}
}
#{Ok}(())
}
)
""",
Expand All @@ -163,14 +192,20 @@ class HttpResponseChecksumCustomization(
codegenContext.symbolProvider.toSymbol(
requestValidationModeMemberInner,
),
)
}
section.registerInterceptor(codegenContext.runtimeConfig, this) {
val interceptorName = "${operationName}HttpResponseChecksumMutationInterceptor"
rustTemplate(
"""
$interceptorName
""",
"OperationInputType" to
codegenContext.symbolProvider.toSymbol(
operationShape.inputShape(
codegenContext.model,
),
),
"ValidationModeShape" to
codegenContext.symbolProvider.toSymbol(
requestValidationModeMemberInner,
),
"ResponseChecksumValidation" to
CargoDependency.smithyTypes(codegenContext.runtimeConfig).toType()
.resolve("checksum_config::ResponseChecksumValidation"),
"ConfigBag" to RuntimeType.configBag(codegenContext.runtimeConfig),
)
}
}
Expand Down

This file was deleted.

0 comments on commit 6c9c3da

Please sign in to comment.