Skip to content

Commit 2173361

Browse files
authored
Merge pull request #2345 from adobe/2218-do-not-store-aws-chunked-encoding
Do not store "aws-chunked" encoding
2 parents ea97686 + 8cfb422 commit 2173361

File tree

5 files changed

+76
-18
lines changed

5 files changed

+76
-18
lines changed

CHANGELOG.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
* [PLANNED - 5.x - RELEASE TBD](#planned---5x---release-tbd)
1212
* [Planned changes](#planned-changes)
1313
* [CURRENT - 4.x - THIS VERSION IS UNDER ACTIVE DEVELOPMENT](#current---4x---this-version-is-under-active-development)
14-
* [4.1.1 - PLANNED](#411---planned)
14+
* [4.2.0 - PLANNED](#420---planned)
15+
* [4.1.1](#411)
1516
* [4.1.0](#410)
1617
* [4.0.0](#400)
1718
* [DEPRECATED - 3.x](#deprecated---3x)
@@ -137,18 +138,30 @@ Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
137138

138139
**The current major version 4 will receive new features, dependency updates and bug fixes on a continuous basis.**
139140

140-
## 4.1.1 - PLANNED
141+
## 4.2.0 - PLANNED
141142
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
142143

143144
* Features and fixes
144-
* Content-Encoding: aws-chunked should not be stored (fixes #2218)
145+
* Support checksum algorithm CRC64NVME (fixes #2334)
145146
* Refactorings
146147
* TBD
147148
* Version updates (deliverable dependencies)
148149
* TBD
149150
* Version updates (build dependencies)
150151
* TBD
151152

153+
## 4.1.1
154+
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
155+
156+
* Features and fixes
157+
* Content-Encoding: aws-chunked should not be stored (fixes #2218)
158+
* Refactorings
159+
* none
160+
* Version updates (deliverable dependencies)
161+
* none
162+
* Version updates (build dependencies)
163+
* none
164+
152165
## 4.1.0
153166
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
154167

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: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ 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

35-
private val s3Client = createS3Client(serviceEndpointHttp)
35+
private val s3Client = createS3Client(serviceEndpointHttp, true)
3636

3737
/**
3838
* Unfortunately the S3 API does not persist or return data that would let us verify if signed and chunked encoding
@@ -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,35 @@ 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")
113+
}
114+
}
115+
116+
@Test
117+
@S3VerifiedFailure(
118+
year = 2023,
119+
reason = "Only works with http endpoints"
120+
)
121+
fun `put object creates correct content-encoding, get object returns content-encoding`(testInfo: TestInfo) {
122+
val bucket = givenBucket(testInfo)
123+
val uploadFile = File(UPLOAD_FILE_NAME)
124+
125+
val customEncoding = "my-custom-encoding"
126+
127+
s3Client.putObject(
128+
{
129+
it.bucket(bucket)
130+
it.key(UPLOAD_FILE_NAME)
131+
it.contentEncoding(customEncoding)
132+
},
133+
RequestBody.fromFile(uploadFile)
134+
)
135+
136+
s3Client.getObject {
137+
it.bucket(bucket)
138+
it.key(UPLOAD_FILE_NAME)
139+
}.also {
140+
assertThat(it.response().contentEncoding()).isEqualTo(customEncoding)
112141
}
113142
}
114143
}

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)