-
Notifications
You must be signed in to change notification settings - Fork 937
Description
Describe the bug
Some third-party S3 implementations don't support chunked encoding and require setting S3Configuration.builder().chunkedEncodingEnabled(false)
. Example:
https://www.alibabacloud.com/help/en/oss/developer-reference/use-amazon-s3-sdks-to-access-oss
This config tweak works with S3Client, but is apparently ignored by the S3AsyncClient. Despite having .chunkedEncodingEnabled(false)
, the S3AsyncClient still uses chunked encoding.
Regression Issue
- Select this option if this issue appears to be a regression.
Expected Behavior
We'd expect S3AsyncClient to behave similarly to S3Client, i.e. stop using chunked encoding when .chunkedEncodingEnabled(false)
is specified.
Current Behavior
S3AsyncClient uses chunked encoding despite .chunkedEncodingEnabled(false)
Reproduction Steps
Here's a unit test demonstrating the behavior of both S3Client and S3AsyncClient:
import static com.github.tomakehurst.wiremock.client.WireMock.matching;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static com.github.tomakehurst.wiremock.client.WireMock.put;
import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.matching.UrlPattern;
import java.net.URI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
public class S3ChunkedEncodingTest {
private static WireMockServer server;
@BeforeAll
static void beforeAll() {
server = new WireMockServer(wireMockConfig().dynamicPort());
server.stubFor(put(UrlPattern.ANY).willReturn(ok()));
server.start();
}
@AfterAll
static void afterAll() {
if (server != null) {
server.stop();
}
}
@BeforeEach
void setUp() {
server.resetRequests();
}
@Test
void syncClientChunkedEncodingEnabled() {
try (S3Client client = buildS3Client(buildS3Configuration(true))) {
client.putObject(PutObjectRequest.builder().bucket("bucket").key("foobar").build(), RequestBody.empty());
}
server.verify(putRequestedFor(UrlPattern.ANY)
.withHeader("Content-Encoding", matching("aws-chunked")));
}
@Test
void syncClientChunkedEncodingDisabled() {
try (S3Client client = buildS3Client(buildS3Configuration(false))) {
client.putObject(PutObjectRequest.builder().bucket("bucket").key("foobar").build(), RequestBody.empty());
}
server.verify(putRequestedFor(UrlPattern.ANY)
.withoutHeader("Content-Encoding"));
}
@Test
void asyncClientChunkedEncodingEnabled() {
try (S3AsyncClient client = buildS3AsyncClient(buildS3Configuration(true))) {
client.putObject(PutObjectRequest.builder().bucket("bucket").key("foobar").build(), AsyncRequestBody.empty()).join();
}
server.verify(putRequestedFor(UrlPattern.ANY)
.withHeader("Content-Encoding", matching("aws-chunked")));
}
@Test
void asyncClientChunkedEncodingDisabled() {
// Turns out S3AsyncClient doesn't respect the property disabling chunked encoding. This test will fail.
try (S3AsyncClient client = buildS3AsyncClient(buildS3Configuration(false))) {
client.putObject(PutObjectRequest.builder().bucket("bucket").key("foobar").build(), AsyncRequestBody.empty()).join();
}
server.verify(putRequestedFor(UrlPattern.ANY)
.withoutHeader("Content-Encoding"));
}
@Test
void asyncCrtClientChunkedEncodingEnabled() {
// CRT always uses chunked encoding, there's no property to disable it. See https://github.com/aws/aws-sdk-java-v2/issues/4806
try (S3AsyncClient client = S3AsyncClient.crtBuilder()
.credentialsProvider(dummyCredentials())
.endpointOverride(URI.create(server.baseUrl()))
.build()) {
client.putObject(PutObjectRequest.builder().bucket("bucket").key("foobar").build(), AsyncRequestBody.empty()).join();
}
server.verify(putRequestedFor(UrlPattern.ANY)
.withHeader("Content-Encoding", matching("aws-chunked")));
}
private static S3Configuration buildS3Configuration(boolean chunkedEncoding) {
return S3Configuration.builder()
.chunkedEncodingEnabled(chunkedEncoding)
.build();
}
private static S3Client buildS3Client(S3Configuration s3config) {
return S3Client.builder()
.serviceConfiguration(s3config)
.credentialsProvider(dummyCredentials())
.endpointOverride(URI.create(server.baseUrl()))
.build();
}
private static S3AsyncClient buildS3AsyncClient(S3Configuration s3Config) {
return S3AsyncClient.builder()
.serviceConfiguration(s3Config)
.credentialsProvider(dummyCredentials())
.endpointOverride(URI.create(server.baseUrl()))
.build();
}
private static StaticCredentialsProvider dummyCredentials() {
return StaticCredentialsProvider.create(AwsBasicCredentials.create("dummy", "dummy"));
}
}
Possible Solution
No response
Additional Information/Context
No response
AWS Java SDK version used
2.30.36
JDK version used
openjdk version "17.0.16" 2025-07-15 LTS
Operating System and version
Linux, kernel 6.12.31