Support x-amz-meta-* for Initiate Multipart Upload

Object metadata specified at InitiateMultipartUpload Reqest must be applied to
a manifest at Complete Multipart Upload.

Object metadata is registered in upload information at Initiate Multipart Upload.
So, I modified to acquire Object metadata from upload information,
and to set it to object created by Complete Multipart Upload.

Change-Id: Ib08e236f854f56107f72d4a836eee720a641b655
This commit is contained in:
Masaki Tsukuda
2015-01-19 20:24:07 +09:00
parent a0834c83a4
commit 284e217d5c
2 changed files with 30 additions and 8 deletions

View File

@@ -64,17 +64,22 @@ DEFAULT_MAX_UPLOADS = 1000
MAX_COMPLETE_UPLOAD_BODY_SIZE = 2048 * 1024
def _check_upload_info(req, app, upload_id):
def _get_upload_info(req, app, upload_id):
container = req.container_name + MULTIUPLOAD_SUFFIX
obj = '%s/%s' % (req.object_name, upload_id)
try:
req.get_response(app, 'HEAD', container=container, obj=obj)
return req.get_response(app, 'HEAD', container=container, obj=obj)
except NoSuchKey:
raise NoSuchUpload(upload_id=upload_id)
def _check_upload_info(req, app, upload_id):
_get_upload_info(req, app, upload_id)
class PartController(Controller):
"""
Handles the following APIs:
@@ -402,7 +407,12 @@ class UploadController(Controller):
Handles Complete Multipart Upload.
"""
upload_id = req.params['uploadId']
_check_upload_info(req, self.app, upload_id)
resp = _get_upload_info(req, self.app, upload_id)
headers = {}
for key, val in resp.headers.iteritems():
_key = key.lower()
if _key.startswith('x-amz-meta-'):
headers['x-object-meta-' + _key[11:]] = val
# Query for the objects in the segments area to make sure it completed
query = {
@@ -454,7 +464,8 @@ class UploadController(Controller):
try:
# TODO: add support for versioning
resp = req.get_response(self.app, 'PUT', body=dumps(manifest),
query={'multipart-manifest': 'put'})
query={'multipart-manifest': 'put'},
headers=headers)
except BadSwiftRequest as e:
msg = str(e)
if msg.startswith('Each segment, except the last, '

View File

@@ -77,7 +77,7 @@ class TestSwift3MultiUpload(Swift3TestCase):
self.swift.register('GET', segment_bucket, swob.HTTPOk, {},
object_list)
self.swift.register('HEAD', segment_bucket + '/object/X',
swob.HTTPOk, {}, None)
swob.HTTPOk, {'x-object-meta-foo': 'bar'}, None)
self.swift.register('PUT', segment_bucket + '/object/X',
swob.HTTPCreated, {}, None)
self.swift.register('DELETE', segment_bucket + '/object/X',
@@ -345,11 +345,15 @@ class TestSwift3MultiUpload(Swift3TestCase):
req = Request.blank('/bucket/object?uploads',
environ={'REQUEST_METHOD': 'POST'},
headers={'Authorization':
'AWS test:tester:hmac'})
'AWS test:tester:hmac',
'x-amz-meta-foo': 'bar'})
status, headers, body = self.call_swift3(req)
fromstring(body, 'InitiateMultipartUploadResult')
self.assertEquals(status.split()[0], '200')
_, _, req_headers = self.swift.calls_with_headers[-1]
self.assertEquals(req_headers.get('X-Object-Meta-Foo'), 'bar')
@s3acl(s3acl_only=True)
@patch('swift3.controllers.multi_upload.unique_id', lambda: 'X')
def test_object_multipart_upload_initiate_s3acl(self):
@@ -357,12 +361,14 @@ class TestSwift3MultiUpload(Swift3TestCase):
environ={'REQUEST_METHOD': 'POST'},
headers={'Authorization':
'AWS test:tester:hmac',
'x-amz-acl': 'public-read'})
'x-amz-acl': 'public-read',
'x-amz-meta-foo': 'bar'})
status, headers, body = self.call_swift3(req)
fromstring(body, 'InitiateMultipartUploadResult')
self.assertEquals(status.split()[0], '200')
_, _, req_headers = self.swift.calls_with_headers[-1]
self.assertEquals(req_headers.get('X-Object-Meta-Foo'), 'bar')
tmpacl_header = req_headers.get(sysmeta_header('object', 'tmpacl'))
self.assertTrue(tmpacl_header)
acl_header = encode_acl('object',
@@ -390,6 +396,9 @@ class TestSwift3MultiUpload(Swift3TestCase):
fromstring(body, 'CompleteMultipartUploadResult')
self.assertEquals(status.split()[0], '200')
_, _, headers = self.swift.calls_with_headers[-2]
self.assertEquals(headers.get('X-Object-Meta-Foo'), 'bar')
@s3acl(s3acl_only=True)
def test_object_multipart_upload_complete_s3acl(self):
acl_headers = encode_acl('object', ACLPublicRead(Owner('test:tester',
@@ -397,6 +406,7 @@ class TestSwift3MultiUpload(Swift3TestCase):
headers = {}
headers[sysmeta_header('object', 'tmpacl')] = \
acl_headers.get(sysmeta_header('object', 'acl'))
headers['X-Object-Meta-Foo'] = 'bar'
self.swift.register('HEAD', '/v1/AUTH_test/bucket+segments/object/X',
swob.HTTPOk, headers, None)
req = Request.blank('/bucket/object?uploadId=X',
@@ -407,7 +417,8 @@ class TestSwift3MultiUpload(Swift3TestCase):
fromstring(body, 'CompleteMultipartUploadResult')
self.assertEquals(status.split()[0], '200')
_, _, headers = self.swift.calls_with_headers[-1]
_, _, headers = self.swift.calls_with_headers[-2]
self.assertEquals(headers.get('X-Object-Meta-Foo'), 'bar')
self.assertEquals(tostring(ACLPublicRead(Owner('test:tester',
'test:tester')).elem()),
tostring(decode_acl('object', headers).elem()))