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")