Skip to content

PutObject does not add Content-Length in the headers when it is specified in the parameters and the body is not Seekable #2511

Closed
@riftsin

Description

Describe the bug

Hello,

When you do a PutObject like this:

buf := []byte{"just some random data"}
r, w := io.Pipe()
defer w.Close()
go func() {
                defer r.Close()
                _, err := s3Client.PutObject(context.TODO(), &s3.PutObjectInput{
                    Bucket:        aws.String("bucket"),
                    Key:           aws.String("screenshot.png"),
                    Body:          r,
                    ContentLength: aws.Int64(len(buf)),
                },
                    s3Client.optionFunc,
                    s3.WithAPIOptions(v4.SwapComputePayloadSHA256ForUnsignedPayloadMiddleware),
                )
                if err != nil {
                  log.Println(err)
                }
}()
io.Copy(w, bytes.NewReader(buf))

You get a SignatureDoesMatchError.

The reason for this is that the header Content-Length is not set in the Request as you can see in the following logs (even though it is set in the canonical request)

---[ CANONICAL STRING  ]-----------------------------
PUT
/bucket/screenshot.png
x-id=PutObject
accept-encoding:identity
amz-sdk-invocation-id:471a9f15-9cbc-4ade-a909-e15f847a4741
amz-sdk-request:attempt=1; max=1
content-length:172595
content-type:application/octet-stream
host:s3.eu-west-3.amazonaws.com
x-amz-content-sha256:UNSIGNED-PAYLOAD
x-amz-date:20240221T103126Z

accept-encoding;amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-content-sha256;x-amz-date
UNSIGNED-PAYLOAD
---[ STRING TO SIGN ]--------------------------------
AWS4-HMAC-SHA256
20240221T103126Z
20240221/eu-west-3/s3/aws4_request
3060f414e9bfb0d526ba52e0e5c5f889f37bb61005017d58804be9d38d0b657c
-----------------------------------------------------
SDK 2024/02/21 11:31:26 DEBUG Request
PUT /bucket/screenshot.png?x-id=PutObject HTTP/1.1
Host: s3.eu-west-3.amazonaws.com
User-Agent: aws-sdk-go-v2/1.21.2 os/macos lang/go#1.22.0 md/GOOS#darwin md/GOARCH#arm64 api/s3#1.38.5
Transfer-Encoding: chunked
Accept-Encoding: identity
Amz-Sdk-Invocation-Id: 471a9f15-9cbc-4ade-a909-e15f847a4741
Amz-Sdk-Request: attempt=1; max=1
Authorization: AWS4-HMAC-SHA256 Credential=AKIA***/20240221/eu-west-3/s3/aws4_request, SignedHeaders=accept-encoding;amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-content-sha256;x-amz-date, Signature=e0ebe472d82ea11f46d2dd02c74055f5ec81e9ddf66ca69cd4211248649c3a31
Content-Type: application/octet-stream
X-Amz-Content-Sha256: UNSIGNED-PAYLOAD
X-Amz-Date: 20240221T103126Z

Expected Behavior

I would expect the content length to be set when I specifiy it using the Content-Length parameter of PutObject.

Current Behavior

The Content-Length header is not set and therefore the request fails with a SignatureDoesNotMatch error.

Reproduction Steps

Just use the code in the example (left out the boiler plate)

Possible Solution

No response

Additional Information/Context

No response

AWS Go SDK V2 Module Versions Used

In the example this was used

    github.com/aws/aws-sdk-go-v2 v1.21.2
    github.com/aws/aws-sdk-go-v2/config v1.18.38
    github.com/aws/aws-sdk-go-v2/credentials v1.13.36
    github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5

However I have tested it with aws-sdk-go-v2 v1.25.0 and I get the same behavior

Compiler and Version used

1.22 darwin/arm64

Operating System and version

MacOS Ventura

Activity

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

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions