Skip to content

Commit

Permalink
Reintroduce boto#221
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesls committed Mar 4, 2014
1 parent 9af068d commit c56ccc0
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
11 changes: 10 additions & 1 deletion botocore/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

import six

from botocore.compat import urlsplit, urlunsplit, unquote, json
from botocore.compat import urlsplit, urlunsplit, unquote, json, quote
from botocore import retryhandler
import botocore.auth

Expand Down Expand Up @@ -191,6 +191,13 @@ def signature_overrides(service_data, service_name, session, **kwargs):
service_data['signature_version'] = signature_version_override


def quote_source_header(params, **kwargs):
if params['headers'] and 'x-amz-copy-source' in params['headers']:
value = params['headers']['x-amz-copy-source']
params['headers']['x-amz-copy-source'] = quote(
value.encode('utf-8'), '/~')


# This is a list of (event_name, handler).
# When a Session is created, everything in this list will be
# automatically registered with that Session.
Expand All @@ -205,6 +212,8 @@ def signature_overrides(service_data, service_name, session, **kwargs):
('before-call.s3.PutBucketLifecycle', calculate_md5),
('before-call.s3.PutBucketCors', calculate_md5),
('before-call.s3.DeleteObjects', calculate_md5),
('before-call.s3.UploadPartCopy', quote_source_header),
('before-call.s3.CopyObject', quote_source_header),
('before-auth.s3', fix_s3_host),
('service-created', register_retries_for_service),
('creating-endpoint.s3', maybe_switch_to_s3sigv4),
Expand Down
33 changes: 33 additions & 0 deletions tests/integration/test_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,5 +361,38 @@ def test_reset_stream_on_redirects(self):
self.assertEqual(data['Body'].read(), b'foo' * 1024)


class TestS3Copy(BaseS3Test):
def setUp(self):
super(TestS3Copy, self).setUp()
self.bucket_name = 'botocoretest%s-%s' % (
int(time.time()), random.randint(1, 1000))
self.bucket_location = 'us-west-2'

operation = self.service.get_operation('CreateBucket')
operation.call(self.endpoint, bucket=self.bucket_name,
create_bucket_configuration={'LocationConstraint': self.bucket_location})

def tearDown(self):
operation = self.service.get_operation('DeleteBucket')
operation.call(self.endpoint, bucket=self.bucket_name)

def test_copy_with_quoted_char(self):
key_name = 'a+b/foo'
self.create_object(key_name=key_name)

operation = self.service.get_operation('CopyObject')
http, parsed = operation.call(
self.endpoint, bucket=self.bucket_name, key=key_name + 'bar',
copy_source='%s/%s' % (self.bucket_name, key_name))
self.assertEqual(http.status_code, 200)

# Now verify we can retrieve the copied object.
operation = self.service.get_operation('GetObject')
response = operation.call(self.endpoint, bucket=self.bucket_name,
key=key_name + 'bar')
data = response[1]
self.assertEqual(data['Body'].read().decode('utf-8'), 'foo')


if __name__ == '__main__':
unittest.main()

0 comments on commit c56ccc0

Please sign in to comment.