Skip to content

Commit cce1e02

Browse files
committed
Do not store "aws-chunked" encoding
AWS docs specify that this encoding is not persisted or returned if it's the only value sent in the "Content-Encoding" header. Fixes #2218
1 parent 561344c commit cce1e02

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/AwsChunkedEndcodingIT.kt renamed to integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/AwsChunkedEncodingIT.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import java.io.InputStream
3030
/**
3131
* Chunked encoding with signing is only active in AWS SDK v2 when endpoint is http
3232
*/
33-
internal class AwsChunkedEndcodingIT : S3TestBase() {
33+
internal class AwsChunkedEncodingIT : S3TestBase() {
3434

3535
private val s3Client = createS3Client(serviceEndpointHttp)
3636

@@ -68,11 +68,11 @@ internal class AwsChunkedEndcodingIT : S3TestBase() {
6868
s3Client.getObject {
6969
it.bucket(bucket)
7070
it.key(UPLOAD_FILE_NAME)
71-
}.also { getObjectResponse ->
72-
assertThat(getObjectResponse.response().eTag()).isEqualTo(expectedEtag)
73-
assertThat(getObjectResponse.response().contentLength()).isEqualTo(uploadFile.length())
74-
75-
getObjectResponse.response().checksumSHA256().also {
71+
}.also {
72+
assertThat(it.response().eTag()).isEqualTo(expectedEtag)
73+
assertThat(it.response().contentLength()).isEqualTo(uploadFile.length())
74+
assertThat(it.response().contentEncoding()).isNotEqualTo("aws-chunked")
75+
it.response().checksumSHA256().also {
7676
assertThat(it).isNotBlank
7777
assertThat(it).isEqualTo(expectedChecksum)
7878
}
@@ -109,6 +109,7 @@ internal class AwsChunkedEndcodingIT : S3TestBase() {
109109
}.also {
110110
assertThat(it.response().eTag()).isEqualTo(expectedEtag)
111111
assertThat(it.response().contentLength()).isEqualTo(uploadFile.length())
112+
assertThat(it.response().contentEncoding()).isNotEqualTo("aws-chunked")
112113
}
113114
}
114115
}

integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/S3TestBase.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ internal abstract class S3TestBase {
227227
@AfterEach
228228
fun cleanupStores() {
229229
for (bucket in _s3Client.listBuckets().buckets()) {
230-
if(bucket.name() == "testputandgetretention-545488000") {return}
231230
//Empty all buckets
232231
deleteMultipartUploads(bucket)
233232
deleteObjectsInBucket(bucket, isObjectLockEnabled(bucket))

server/src/main/java/com/adobe/testing/s3mock/service/ServiceBase.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
import static com.adobe.testing.s3mock.S3Exception.BAD_REQUEST_CONTENT;
2525
import static com.adobe.testing.s3mock.util.AwsHttpHeaders.X_AMZ_DECODED_CONTENT_LENGTH;
2626
import static com.adobe.testing.s3mock.util.HeaderUtil.checksumAlgorithmFromSdk;
27-
import static com.adobe.testing.s3mock.util.HeaderUtil.isChunked;
28-
import static com.adobe.testing.s3mock.util.HeaderUtil.isChunkedAndV4Signed;
27+
import static com.adobe.testing.s3mock.util.HeaderUtil.isChunkedEncoding;
28+
import static com.adobe.testing.s3mock.util.HeaderUtil.isV4Signed;
2929

3030
import com.adobe.testing.s3mock.dto.ChecksumAlgorithm;
3131
import com.adobe.testing.s3mock.util.AbstractAwsInputStream;
@@ -93,9 +93,9 @@ public Pair<Path, String> toTempFile(InputStream inputStream) {
9393
private InputStream wrapStream(InputStream dataStream, HttpHeaders headers) {
9494
var lengthHeader = headers.getFirst(X_AMZ_DECODED_CONTENT_LENGTH);
9595
var length = lengthHeader == null ? -1 : Long.parseLong(lengthHeader);
96-
if (isChunkedAndV4Signed(headers)) {
96+
if (isV4Signed(headers)) {
9797
return new AwsChunkedDecodingChecksumInputStream(dataStream, length);
98-
} else if (isChunked(headers)) {
98+
} else if (isChunkedEncoding(headers)) {
9999
return new AwsUnsignedChunkedDecodingChecksumInputStream(dataStream, length);
100100
} else {
101101
return dataStream;

server/src/main/java/com/adobe/testing/s3mock/util/HeaderUtil.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ public static Map<String, String> storeHeadersFrom(HttpHeaders headers) {
116116
header -> (equalsIgnoreCase(header, HttpHeaders.EXPIRES)
117117
|| equalsIgnoreCase(header, HttpHeaders.CONTENT_LANGUAGE)
118118
|| equalsIgnoreCase(header, HttpHeaders.CONTENT_DISPOSITION)
119-
|| equalsIgnoreCase(header, HttpHeaders.CONTENT_ENCODING)
119+
|| (equalsIgnoreCase(header, HttpHeaders.CONTENT_ENCODING)
120+
&& !isOnlyChunkedEncoding(headers))
120121
|| equalsIgnoreCase(header, HttpHeaders.CACHE_CONTROL)
121122
));
122123
}
@@ -152,19 +153,35 @@ && isNotBlank(entry.getValue().get(0))) {
152153
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));
153154
}
154155

155-
public static boolean isChunkedAndV4Signed(HttpHeaders headers) {
156+
public static boolean isV4Signed(HttpHeaders headers) {
156157
var sha256Header = headers.getFirst(X_AMZ_CONTENT_SHA256);
157158
return sha256Header != null
158159
&& (sha256Header.equals(STREAMING_AWS_4_HMAC_SHA_256_PAYLOAD)
159160
|| sha256Header.equals(STREAMING_AWS_4_HMAC_SHA_256_PAYLOAD_TRAILER));
160161
}
161162

162-
public static boolean isChunked(HttpHeaders headers) {
163+
public static boolean isChunkedEncoding(HttpHeaders headers) {
163164
var contentEncodingHeaders = headers.get(HttpHeaders.CONTENT_ENCODING);
164165
return (contentEncodingHeaders != null
165166
&& (contentEncodingHeaders.contains(AWS_CHUNKED)));
166167
}
167168

169+
/**
170+
* Check if aws-chunked is the only "Content-Encoding" header.
171+
* <quote>
172+
* If aws-chunked is the only value that you pass in the content-encoding header, S3 considers
173+
* the content-encoding header empty and does not return this header when your retrieve the
174+
* object.
175+
* </quote>
176+
* See <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html">API</a>
177+
*/
178+
private static boolean isOnlyChunkedEncoding(HttpHeaders headers) {
179+
var contentEncodingHeaders = headers.get(HttpHeaders.CONTENT_ENCODING);
180+
return (contentEncodingHeaders != null
181+
&& contentEncodingHeaders.size() == 1
182+
&& (contentEncodingHeaders.contains(AWS_CHUNKED)));
183+
}
184+
168185
public static MediaType mediaTypeFrom(final String contentType) {
169186
try {
170187
return MediaType.parseMediaType(contentType);

0 commit comments

Comments
 (0)