From 8413ace10bf30ec61134685fe8d15b6ce8159935 Mon Sep 17 00:00:00 2001 From: Naoto Nishizono Date: Thu, 15 Jan 2015 13:23:55 +0900 Subject: [PATCH] Fix response of Upload Part Copy requests Change-Id: I0c66ac3b62ad8fa1f27b627d0f25f8def556b265 --- swift3/controllers/multi_upload.py | 3 ++- swift3/controllers/obj.py | 9 +-------- swift3/response.py | 9 +++++++++ swift3/test/unit/test_multi_upload.py | 21 ++++++++++++++++++++- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/swift3/controllers/multi_upload.py b/swift3/controllers/multi_upload.py index 1c2fcfc3..64d1cf13 100644 --- a/swift3/controllers/multi_upload.py +++ b/swift3/controllers/multi_upload.py @@ -110,7 +110,8 @@ class PartController(Controller): resp = req.get_response(self.app) - # TODO: set xml body for copy requests. + if 'X-Amz-Copy-Source' in req.headers: + resp.append_copy_resp_body() resp.status = 200 return resp diff --git a/swift3/controllers/obj.py b/swift3/controllers/obj.py index 09af7045..817405f9 100644 --- a/swift3/controllers/obj.py +++ b/swift3/controllers/obj.py @@ -18,7 +18,6 @@ from swift.common.swob import Range, content_range_header_value from swift3.controllers.base import Controller from swift3.response import S3NotImplemented, InvalidRange, HTTPPartialContent -from swift3.etree import Element, SubElement, tostring class ObjectController(Controller): @@ -97,13 +96,7 @@ class ObjectController(Controller): resp = req.get_response(self.app) if 'X-Amz-Copy-Source' in req.headers: - elem = Element('CopyObjectResult') - SubElement(elem, 'LastModified').text = \ - resp.last_modified.isoformat()[:-6] + '.000Z' - SubElement(elem, 'ETag').text = '"%s"' % resp.etag - resp.body = tostring(elem) - resp.headers['Content-Type'] = 'application/xml' - resp.etag = None + resp.append_copy_resp_body() resp.status = HTTP_OK return resp diff --git a/swift3/response.py b/swift3/response.py index 57f267ad..0ec38e07 100644 --- a/swift3/response.py +++ b/swift3/response.py @@ -135,6 +135,15 @@ class Response(ResponseBase, swob.Response): return resp + def append_copy_resp_body(self): + elem = Element('CopyObjectResult') + SubElement(elem, 'LastModified').text = \ + self.last_modified.isoformat()[:-6] + '.000Z' + SubElement(elem, 'ETag').text = '"%s"' % self.etag + self.headers['Content-Type'] = 'application/xml' + self.body = tostring(elem) + self.etag = None + HTTPOk = partial(Response, status=200) HTTPCreated = partial(Response, status=201) diff --git a/swift3/test/unit/test_multi_upload.py b/swift3/test/unit/test_multi_upload.py index 32fd805a..eeeea0f5 100644 --- a/swift3/test/unit/test_multi_upload.py +++ b/swift3/test/unit/test_multi_upload.py @@ -60,6 +60,9 @@ class TestSwift3MultiUpload(Swift3TestCase): super(TestSwift3MultiUpload, self).setUp() segment_bucket = '/v1/AUTH_test/bucket+segments' + self.etag = '7dfa07a8e59ddbcd1dc84d4c4f82aea1' + last_modified = 'Fri, 01 Apr 2014 12:00:00 GMT' + put_headers = {'etag': self.etag, 'last-modified': last_modified} objects = map(lambda item: {'name': item[0], 'last_modified': item[1], 'hash': item[2], 'bytes': item[3]}, @@ -80,7 +83,7 @@ class TestSwift3MultiUpload(Swift3TestCase): self.swift.register('GET', segment_bucket + '/object/invalid', swob.HTTPNotFound, {}, None) self.swift.register('PUT', segment_bucket + '/object/X/1', - swob.HTTPCreated, {}, None) + swob.HTTPCreated, put_headers, None) self.swift.register('DELETE', segment_bucket + '/object/X/1', swob.HTTPNoContent, {}, None) self.swift.register('DELETE', segment_bucket + '/object/X/2', @@ -673,6 +676,22 @@ class TestSwift3MultiUpload(Swift3TestCase): 'X-Amz-Copy-Source': src_path}) return self.call_swift3(req) + @s3acl + def test_upload_part_copy(self): + iso_format = '2014-04-01T12:00:00.000Z' + status, headers, body = \ + self._test_copy_for_s3acl('test:tester') + self.assertEquals(status.split()[0], '200') + self.assertEquals(headers['Content-Type'], 'application/xml') + self.assertTrue(headers.get('etag') is None) + elem = fromstring(body, 'CopyObjectResult') + self.assertEquals(elem.find('LastModified').text, iso_format) + self.assertEquals(elem.find('ETag').text, '"%s"' % self.etag) + + _, _, headers = self.swift.calls_with_headers[-1] + self.assertEquals(headers['X-Copy-From'], '/src_bucket/src_obj') + self.assertEquals(headers['Content-Length'], '0') + @s3acl(s3acl_only=True) def test_upload_part_copy_acl_with_owner_permission(self): status, headers, body = \