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:
@@ -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, '
|
||||
|
||||
@@ -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()))
|
||||
|
||||
Reference in New Issue
Block a user