S3: Do not unquote the key two times on multipart upload complete (#6287)

This commit is contained in:
vdytyniak-exos 2023-05-08 20:14:20 +03:00 committed by GitHub
parent 1e455610ab
commit 7a4eac06d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 9 deletions

View File

@ -1888,9 +1888,13 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
return new_key return new_key
def put_object_acl( def put_object_acl(
self, bucket_name: str, key_name: str, acl: Optional[FakeAcl] self,
bucket_name: str,
key_name: str,
acl: Optional[FakeAcl],
key_is_clean: bool = False,
) -> None: ) -> None:
key = self.get_object(bucket_name, key_name) key = self.get_object(bucket_name, key_name, key_is_clean=key_is_clean)
# TODO: Support the XML-based ACL format # TODO: Support the XML-based ACL format
if key is not None: if key is not None:
key.set_acl(acl) key.set_acl(acl)

View File

@ -2173,7 +2173,12 @@ class S3Response(BaseResponse):
) )
key.set_metadata(multipart.metadata) key.set_metadata(multipart.metadata)
self.backend.set_key_tags(key, multipart.tags) self.backend.set_key_tags(key, multipart.tags)
self.backend.put_object_acl(bucket_name, key.name, multipart.acl) self.backend.put_object_acl(
bucket_name=bucket_name,
key_name=key.name,
acl=multipart.acl,
key_is_clean=True,
)
template = self.response_template(S3_MULTIPART_COMPLETE_RESPONSE) template = self.response_template(S3_MULTIPART_COMPLETE_RESPONSE)
headers: Dict[str, Any] = {} headers: Dict[str, Any] = {}

View File

@ -107,34 +107,35 @@ def test_multipart_upload_too_small():
) )
@pytest.mark.parametrize("key", ["the-key", "the%20key"])
@mock_s3 @mock_s3
@reduced_min_part_size @reduced_min_part_size
def test_multipart_upload(): def test_multipart_upload(key: str):
s3 = boto3.resource("s3", region_name=DEFAULT_REGION_NAME) s3 = boto3.resource("s3", region_name=DEFAULT_REGION_NAME)
client = boto3.client("s3", region_name=DEFAULT_REGION_NAME) client = boto3.client("s3", region_name=DEFAULT_REGION_NAME)
s3.create_bucket(Bucket="foobar") s3.create_bucket(Bucket="foobar")
part1 = b"0" * REDUCED_PART_SIZE part1 = b"0" * REDUCED_PART_SIZE
part2 = b"1" part2 = b"1"
mp = client.create_multipart_upload(Bucket="foobar", Key="the-key") mp = client.create_multipart_upload(Bucket="foobar", Key=key)
up1 = client.upload_part( up1 = client.upload_part(
Body=BytesIO(part1), Body=BytesIO(part1),
PartNumber=1, PartNumber=1,
Bucket="foobar", Bucket="foobar",
Key="the-key", Key=key,
UploadId=mp["UploadId"], UploadId=mp["UploadId"],
) )
up2 = client.upload_part( up2 = client.upload_part(
Body=BytesIO(part2), Body=BytesIO(part2),
PartNumber=2, PartNumber=2,
Bucket="foobar", Bucket="foobar",
Key="the-key", Key=key,
UploadId=mp["UploadId"], UploadId=mp["UploadId"],
) )
client.complete_multipart_upload( client.complete_multipart_upload(
Bucket="foobar", Bucket="foobar",
Key="the-key", Key=key,
MultipartUpload={ MultipartUpload={
"Parts": [ "Parts": [
{"ETag": up1["ETag"], "PartNumber": 1}, {"ETag": up1["ETag"], "PartNumber": 1},
@ -144,7 +145,7 @@ def test_multipart_upload():
UploadId=mp["UploadId"], UploadId=mp["UploadId"],
) )
# we should get both parts as the key contents # we should get both parts as the key contents
response = client.get_object(Bucket="foobar", Key="the-key") response = client.get_object(Bucket="foobar", Key=key)
response["Body"].read().should.equal(part1 + part2) response["Body"].read().should.equal(part1 + part2)