Skip to content

Conversation

@zoewangg
Copy link
Contributor

@zoewangg zoewangg commented Nov 6, 2025

Motivation and Context

When streaming operations have HTTP checksum traits, they need chunked encoding enabled in the auth signer. Previously, this had to be manually configured. This PR automates the process by detecting these operations during code generation and automatically adding the CHUNK_ENCODING_ENABLED property to their auth scheme metadata.

Additionally, the ModelAuthSchemeKnowledgeIndex class was refactored to improve maintainability and clarity.

Modifications

  1. Automatic Chunked Encoding Detection:
    • Added shouldUseChunkedEncoding() to detect streaming operations with HTTP checksum traits
    • Automatically marks these operations with CHUNK_ENCODING_ENABLED property in auth scheme metadata

  2. Refactored ModelAuthSchemeKnowledgeIndex:
    • Extracted helper methods for better separation of concerns:
    • operationsShouldUseChunkedEncoding() - Identifies operations needing chunked encoding
    • processOperationsWithAuthTraits() - Handles main processing loop
    • determineAuthScheme() - Decides between custom auth or service defaults
    • processRemainingChunkedEncodingOperations() - Handles chunked ops with service defaults
    • hasAuthTrait() - Filters operations and validates auth traits
    • Generalized validation logic with hasCustomServiceAuthSchemeOverride() instead of hardcoded service checks
    • Added javadocs explaining flow and special cases

  3. Test Updates:
    • Added test models for S3 and S3Control with chunked encoding scenarios
    • Updated existing tests to verify chunked encoding property is correctly added

Testing

• Added new test cases for streaming operations with HTTP checksums
• Verified chunked encoding property is correctly added to auth metadata
• All existing unit tests pass
• Local mvn install succeeds

Types of changes

• [x] New feature (non-breaking change which adds functionality)

Checklist

• [x] I have read the CONTRIBUTING document
• [x] Local run of mvn install succeeds
• [x] My code follows the code style of this project
• [x] My change requires a change to the Javadoc documentation
• [x] I have updated the Javadoc documentation accordingly
• [x] I have added tests to cover my changes
• [x] All new and existing tests passed
• [ ] I have added a changelog entry
• [ ] My change is to implement 1.11 parity feature - N/A

License

• [x] I confirm that this pull request can be released under the Apache 2 license

@zoewangg zoewangg requested a review from a team as a code owner November 6, 2025 23:03
@zoewangg zoewangg marked this pull request as draft November 6, 2025 23:04
"requestValidationModeMember": "ChecksumMode",
"responseAlgorithms": ["CRC32C", "CRC32", "SHA1", "SHA256"]
"responseAlgorithms": ["CRC32C", "CRC32", "SHA1", "SHA256"],
"requestAlgorithmMember": "ChecksumAlgorithm"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added requestAlgorithmMember because per smithy doc https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait, either requestAlgorithmMember or requestChecksumRequired is required

The httpChecksum trait MUST define at least one of the request checksumming behavior, by setting the requestAlgorithmMember or requestChecksumRequired property,

.modelProvider(ClientTestModels::serviceS3)
.classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
.caseName("mini-s3")
.caseName("s3-test")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to use real s3 model because why not 🤷🏼‍♀️ and it may help us catch S3 issues

.caseName("s3-test")
.outputFileSuffix("fallback-provider")
.build(),
// S3 control
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added s3 control because it uses legacy signature version

}

/**
* Returns a map from a list of operations to the list of auth-types modeled for those operations. The {@link AuthTrait}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried my best to explain what this method does here because it's quite hard to understand, lmk if it's still not clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I think the explanation is good.

@zoewangg zoewangg force-pushed the zoewang/chunkedEncoding branch from baff246 to 839f640 Compare November 7, 2025 00:45
Copy link
Contributor

@sugmanue sugmanue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits, overall looks good to me.

}

/**
* Returns a map from a list of operations to the list of auth-types modeled for those operations. The {@link AuthTrait}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I think the explanation is good.

Comment on lines +83 to +85
RegionSet regionSet = Optional.ofNullable(params.regionSet()).orElseGet(
() -> Optional.ofNullable(sigv4aAuthScheme.signingRegionSet())
.filter(set -> !CollectionUtils.isNullOrEmpty(set)).map(RegionSet::create).orElse(null));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to this change, but, let's say, this can be improved, two allocs just to write this in a single expression is not a good tradeoff, in my not-so-humble opinion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, to keep this PR small, I will create a separate PR for this

@@ -0,0 +1,3380 @@
{
"version": "1.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please keep this file empty or just keep minimal how much ever required for codegen test

Same for other resource files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the real s3 and s3 control models as of when the PR was created on purpose because I figured it would help us catch s3 changes. LMK if you have concerns

@zoewangg zoewangg marked this pull request as ready for review November 25, 2025 21:31
@zoewangg
Copy link
Contributor Author

DefaultS3AuthSchemeProvider diff

➜ ~ diff -s baseline_s3_auth_scheme_provider.java new_s3_auth_scheme_provider.java
Files baseline_s3_auth_scheme_provider.java and new_s3_auth_scheme_provider.java are identical

DefaultS3FallbackAuthSchemeProvider diff

➜ ~ diff -s baseline_fallback_s3_auth_scheme_provider.java new_fallback_s3_auth_scheme_provider.java
Files baseline_fallback_s3_auth_scheme_provider.java and new_fallback_s3_auth_scheme_provider.java are identical

DefaultS3ControlAuthSchemeProvider diff

➜ ~ diff -s baseline_s3control_auth_scheme_provider.java new_s3control_auth_scheme_provider.java
43c43,45

<                 .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
---
>                 .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id())
>                 .putSignerProperty(AwsV4HttpSigner.DOUBLE_URL_ENCODE, false)
>                 .putSignerProperty(AwsV4HttpSigner.NORMALIZE_PATH, false).build());

@zoewangg zoewangg force-pushed the zoewang/chunkedEncoding branch from 839f640 to 81c108f Compare November 25, 2025 23:07
* https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
*/
@SdkInternalApi
public final class ConfigureSignerInterceptor implements ExecutionInterceptor {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer needed because it's handled in generated auth scheme provider now. See DefaultS3ControlAuthSchemeProvider diff in #6551 (comment)

@sonarqubecloud
Copy link

}

/**
* Determines if an operation should be included based on whether it has auth traits.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: It's not clear what the operation should be included in. Could probably just remove that part.

Map<List<String>, List<AuthSchemeCodegenMetadata>> result = new LinkedHashMap<>();
Set<String> processedChunkedOps = new HashSet<>();

processOperationsWithAuthTraits(chunkedEncodingOps, serviceDefaults, result, processedChunkedOps);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

processedChunkedOps is a bit hard to follow; is there a more descriptive name we can use here? i.e. what does it mean for something to be an "unprocessed" chunked operation? It doesn't use service defaults?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants