From 6c0a2dc374b45028b1d9afe003479bbcd27bb1ac Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen Date: Sat, 21 Sep 2019 09:47:21 +0800 Subject: [PATCH] Fix copying S3 objects with question marks in keys PR #2062 fixes copy for unicode keys. However, the change breaks keys with question marks. Here is an alternative fix that works for both emojis and question marks. I notice this when running the test suite of aiobotocore. One of the tests [1] is broken with moto >= 1.3.8. [1] https://github.com/aio-libs/aiobotocore/blob/0.10.3/tests/test_basic_s3.py#L314-L329 --- moto/s3/responses.py | 4 ++-- tests/test_s3/test_s3.py | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 61ebff9d0..b13da69bd 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -913,11 +913,11 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin): # Copy key # you can have a quoted ?version=abc with a version Id, so work on # we need to parse the unquoted string first - src_key = clean_key_name(request.headers.get("x-amz-copy-source")) + src_key = request.headers.get("x-amz-copy-source") if isinstance(src_key, six.binary_type): src_key = src_key.decode('utf-8') src_key_parsed = urlparse(src_key) - src_bucket, src_key = unquote(src_key_parsed.path).\ + src_bucket, src_key = clean_key_name(src_key_parsed.path).\ lstrip("/").split("/", 1) src_version_id = parse_qs(src_key_parsed.query).get( 'versionId', [None])[0] diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index 336639a8c..abd926950 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -421,18 +421,22 @@ def test_copy_key(): "new-key").get_contents_as_string().should.equal(b"some value") +@parameterized([ + ("the-unicode-💩-key",), + ("key-with?question-mark",), +]) @mock_s3_deprecated -def test_copy_key_with_unicode(): +def test_copy_key_with_special_chars(key_name): conn = boto.connect_s3('the_key', 'the_secret') bucket = conn.create_bucket("foobar") key = Key(bucket) - key.key = "the-unicode-💩-key" + key.key = key_name key.set_contents_from_string("some value") - bucket.copy_key('new-key', 'foobar', 'the-unicode-💩-key') + bucket.copy_key('new-key', 'foobar', key_name) bucket.get_key( - "the-unicode-💩-key").get_contents_as_string().should.equal(b"some value") + key_name).get_contents_as_string().should.equal(b"some value") bucket.get_key( "new-key").get_contents_as_string().should.equal(b"some value")