This is an automated email from the ASF dual-hosted git repository.
fanningpj pushed a commit to branch 1.4.x
in repository https://gitbox.apache.org/repos/asf/pekko-connectors.git
The following commit(s) were added to refs/heads/1.4.x by this push:
new c12c14fcf S3: Fix multipart upload signature mismatch with AWS SDK v2
(#1544) (#1559)
c12c14fcf is described below
commit c12c14fcf75df92243c5767e33e2bfc0cf053c32
Author: PJ Fanning <[email protected]>
AuthorDate: Wed Apr 8 14:43:02 2026 +0200
S3: Fix multipart upload signature mismatch with AWS SDK v2 (#1544) (#1559)
* Initial plan
* Fix UploadPart signature mismatch: add Content-Type and x-amz-trailer to
allowlist; add Content-Length and Content-MD5 to InitiateMultipartUpload
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko-connectors/sessions/73f72669-0f29-44d1-a6ea-f3b21f7b0704
---------
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
---
s3/src/main/resources/reference.conf | 4 +++
.../pekko/stream/connectors/s3/S3HeadersSpec.scala | 32 ++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/s3/src/main/resources/reference.conf
b/s3/src/main/resources/reference.conf
index 4521e6475..c095d11ed 100644
--- a/s3/src/main/resources/reference.conf
+++ b/s3/src/main/resources/reference.conf
@@ -207,6 +207,8 @@ pekko.connectors.s3 {
"Content-Disposition",
"Content-Encoding",
"Content-Language",
+ "Content-Length",
+ "Content-MD5",
"Content-Type",
"Expires",
"x-amz-grant-full-control",
@@ -236,12 +238,14 @@ pekko.connectors.s3 {
"Host",
"Content-Length",
"Content-MD5",
+ "Content-Type",
"x-amz-sdk-checksum-algorithm",
"x-amz-checksum-crc32",
"x-amz-checksum-crc32c",
"x-amz-checksum-crc64nvme",
"x-amz-checksum-sha1",
"x-amz-checksum-sha256",
+ "x-amz-trailer",
"x-amz-server-side-encryption-customer-algorithm",
"x-amz-server-side-encryption-customer-key",
"x-amz-server-side-encryption-customer-key-MD5",
diff --git
a/s3/src/test/scala/org/apache/pekko/stream/connectors/s3/S3HeadersSpec.scala
b/s3/src/test/scala/org/apache/pekko/stream/connectors/s3/S3HeadersSpec.scala
index a5e7cec31..421d7b532 100644
---
a/s3/src/test/scala/org/apache/pekko/stream/connectors/s3/S3HeadersSpec.scala
+++
b/s3/src/test/scala/org/apache/pekko/stream/connectors/s3/S3HeadersSpec.scala
@@ -25,6 +25,12 @@ import org.scalatest.matchers.should.Matchers
import pekko.stream.connectors.s3.impl._
class S3HeadersSpec extends AnyFlatSpecLike with Matchers {
+
+ private lazy val defaultSettings: S3Settings = {
+ val defaultConfig = ConfigFactory.load()
+ S3Settings.apply(defaultConfig.getConfig("pekko.connectors.s3"))
+ }
+
it should "filter headers based on what's allowed" in {
val testOverrideConfig = ConfigFactory.parseString("""
| pekko.connectors.s3 {
@@ -85,6 +91,32 @@ class S3HeadersSpec extends AnyFlatSpecLike with Matchers {
}
+ it should "allow Content-Type header for UploadPart (fix for signature
mismatch with AWS SDK v2)" in {
+ val header = S3Headers().withCustomHeaders(Map("Content-Type" ->
"application/octet-stream"))
+ val result = header.headersFor(UploadPart)(defaultSettings)
+ result.map(_.name()) should contain("Content-Type")
+ }
+
+ it should "allow x-amz-trailer header for UploadPart" in {
+ val header = S3Headers().withCustomHeaders(Map("x-amz-trailer" ->
"x-amz-checksum-sha256"))
+ val result = header.headersFor(UploadPart)(defaultSettings)
+ result.map(_.name()) should contain("x-amz-trailer")
+ }
+
+ it should "allow Content-Length and Content-MD5 headers for
InitiateMultipartUpload" in {
+ val header = S3Headers().withCustomHeaders(Map("Content-Length" -> "0",
"Content-MD5" -> "abc123"))
+ val result = header.headersFor(InitiateMultipartUpload)(defaultSettings)
+ val resultNames = result.map(_.name())
+ resultNames should contain("Content-Length")
+ resultNames should contain("Content-MD5")
+ }
+
+ it should "filter headers not in the allowlist for UploadPart" in {
+ val header = S3Headers().withCustomHeaders(Map("x-amz-acl" ->
"public-read"))
+ val result = header.headersFor(UploadPart)(defaultSettings)
+ result.map(_.name()) should not contain "x-amz-acl"
+ }
+
it should "contain all S3Request types" in {
val actualSet = S3Request.allRequests
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]