diff --git a/botocore/httpchecksum.py b/botocore/httpchecksum.py index a4b7e8648d..5d0a6c17eb 100644 --- a/botocore/httpchecksum.py +++ b/botocore/httpchecksum.py @@ -409,6 +409,12 @@ def _apply_request_trailer_checksum(request): # services such as S3 may require the decoded content length headers["X-Amz-Decoded-Content-Length"] = str(content_length) + if "Content-Length" in headers: + del headers["Content-Length"] + logger.debug( + "Removing the Content-Length header since 'chunked' is specified for Transfer-Encoding." + ) + if isinstance(body, (bytes, bytearray)): body = io.BytesIO(body) diff --git a/tests/functional/test_s3.py b/tests/functional/test_s3.py index 1206b83272..0cee2ee726 100644 --- a/tests/functional/test_s3.py +++ b/tests/functional/test_s3.py @@ -1536,6 +1536,26 @@ def test_trailing_checksum_set(self): body = self.http_stubber.requests[0].body.read() self.assertIn(b"x-amz-checksum-crc32:eCQEmA==", body) + def test_trailing_checksum_set_with_content_length_removes_header(self): + with self.http_stubber: + self.client.put_object( + Bucket="foo", Key="bar", Body="baz", ContentLength=123 + ) + sent_headers = self.get_sent_headers() + self.assertEqual(sent_headers["Content-Encoding"], b"aws-chunked") + self.assertEqual(sent_headers["Transfer-Encoding"], b"chunked") + self.assertEqual( + sent_headers["X-Amz-Trailer"], b"x-amz-checksum-crc32" + ) + self.assertEqual(sent_headers["X-Amz-Decoded-Content-Length"], b"3") + self.assertEqual( + sent_headers["x-amz-content-sha256"], + b"STREAMING-UNSIGNED-PAYLOAD-TRAILER", + ) + body = self.http_stubber.requests[0].body.read() + self.assertIn(b"x-amz-checksum-crc32:eCQEmA==", body) + self.assertNotIn("Content-Length", sent_headers) + def test_trailing_checksum_set_empty_body(self): with self.http_stubber: self.client.put_object(Bucket="foo", Key="bar", Body="") @@ -1686,7 +1706,11 @@ def test_content_sha256_set_s3_on_outpost(self): class TestCanSendIntegerHeaders(BaseSessionTest): def test_int_values_with_sigv4(self): s3 = self.session.create_client( - "s3", config=Config(signature_version="s3v4") + "s3", + config=Config( + signature_version="s3v4", + request_checksum_calculation="when_required", + ), ) with ClientHTTPStubber(s3) as http_stubber: http_stubber.add_response()