diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dac737b..6788515c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Moto Changelog * Supports filtering AMIs by self * Implemented signal_workflow_execution for SWF * Wired SWF backend to the moto server + * Added url decoding to x-amz-copy-source header for copying S3 files * Revamped lambda function storage to do versioning * IOT improvements * RDS improvements diff --git a/moto/s3/responses.py b/moto/s3/responses.py index e3660dea..7b07e4e0 100755 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -4,7 +4,7 @@ import re import six from moto.core.utils import str_to_rfc_1123_datetime -from six.moves.urllib.parse import parse_qs, urlparse +from six.moves.urllib.parse import parse_qs, urlparse, unquote import xmltodict @@ -647,7 +647,7 @@ class ResponseObject(_TemplateEnvironmentMixin): upload_id = query['uploadId'][0] part_number = int(query['partNumber'][0]) if 'x-amz-copy-source' in request.headers: - src = request.headers.get("x-amz-copy-source").lstrip("/") + src = unquote(request.headers.get("x-amz-copy-source")).lstrip("/") src_bucket, src_key = src.split("/", 1) src_range = request.headers.get( 'x-amz-copy-source-range', '').split("bytes=")[-1] @@ -689,7 +689,7 @@ class ResponseObject(_TemplateEnvironmentMixin): if 'x-amz-copy-source' in request.headers: # Copy key - src_key_parsed = urlparse(request.headers.get("x-amz-copy-source")) + src_key_parsed = urlparse(unquote(request.headers.get("x-amz-copy-source"))) src_bucket, src_key = src_key_parsed.path.lstrip("/").split("/", 1) src_version_id = parse_qs(src_key_parsed.query).get( 'versionId', [None])[0]