Merge "Fix response of PUT Object Copy requests"

This commit is contained in:
Jenkins
2015-01-15 02:26:57 +00:00
committed by Gerrit Code Review
2 changed files with 51 additions and 31 deletions

View File

@@ -17,8 +17,7 @@ from swift.common.http import HTTP_OK
from swift.common.swob import Range, content_range_header_value
from swift3.controllers.base import Controller
from swift3.response import HTTPOk, S3NotImplemented, InvalidRange,\
HTTPPartialContent
from swift3.response import S3NotImplemented, InvalidRange, HTTPPartialContent
from swift3.etree import Element, SubElement, tostring
@@ -99,9 +98,12 @@ class ObjectController(Controller):
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
body = tostring(elem, use_s3ns=False)
return HTTPOk(body=body, headers=resp.headers)
resp.body = tostring(elem)
resp.headers['Content-Type'] = 'application/xml'
resp.etag = None
resp.status = HTTP_OK
return resp

View File

@@ -24,6 +24,7 @@ from swift.common.swob import Request
from swift3.test.unit import Swift3TestCase
from swift3.test.unit.test_s3_acl import s3acl
from swift3.subresource import ACL, User, encode_acl, Owner, Grant
from swift3.etree import fromstring
class TestSwift3Obj(Swift3TestCase):
@@ -32,17 +33,23 @@ class TestSwift3Obj(Swift3TestCase):
super(TestSwift3Obj, self).setUp()
self.object_body = 'hello'
etag = hashlib.md5(self.object_body).hexdigest()
self.etag = hashlib.md5(self.object_body).hexdigest()
self.last_modified = 'Fri, 01 Apr 2014 12:00:00 GMT'
self.response_headers = {'Content-Type': 'text/html',
'Content-Length': len(self.object_body),
'x-object-meta-test': 'swift',
'etag': etag,
'last-modified': '2011-01-05T02:19:14.275290'}
'etag': self.etag,
'last-modified': self.last_modified}
self.swift.register('GET', '/v1/AUTH_test/bucket/object',
swob.HTTPOk, self.response_headers,
self.object_body)
self.swift.register('PUT', '/v1/AUTH_test/bucket/object',
swob.HTTPCreated,
{'etag': self.etag,
'last-modified': self.last_modified},
None)
def _test_object_GETorHEAD(self, method):
req = Request.blank('/bucket/object',
@@ -332,15 +339,10 @@ class TestSwift3Obj(Swift3TestCase):
self.assertEquals(headers['etag'], etag)
def test_object_PUT_headers(self):
etag = '7dfa07a8e59ddbcd1dc84d4c4f82aea1'
content_md5 = etag.decode('hex').encode('base64').strip()
content_md5 = self.etag.decode('hex').encode('base64').strip()
self.swift.register('HEAD', '/v1/AUTH_test/some/source',
swob.HTTPOk, {}, None)
self.swift.register('PUT', '/v1/AUTH_test/bucket/object',
swob.HTTPCreated,
{'etag': etag},
None)
req = Request.blank(
'/bucket/object',
environ={'REQUEST_METHOD': 'PUT'},
@@ -352,17 +354,19 @@ class TestSwift3Obj(Swift3TestCase):
req.date = datetime.now()
req.content_type = 'text/plain'
status, headers, body = self.call_swift3(req)
# Check that swift3 returns an etag header.
self.assertEquals(headers['etag'], '"%s"' % etag)
# Check that swift3 dones not return an etag header,
# sepcified copy source.
self.assertTrue(headers.get('etag') is None)
self.assertEquals(headers['last-modified'], self.last_modified)
_, _, headers = self.swift.calls_with_headers[-1]
# Check that swift3 converts a Content-MD5 header into an etag.
self.assertEquals(headers['ETag'], etag)
self.assertEquals(headers['ETag'], self.etag)
self.assertEquals(headers['X-Object-Meta-Something'], 'oh hai')
self.assertEquals(headers['X-Copy-From'], '/some/source')
self.assertEquals(headers['Content-Length'], '0')
def _test_object_PUT_copy_headers(self, head_resp, put_header):
def _test_object_PUT_copy(self, head_resp, put_header={}):
account = 'test:tester'
grants = [Grant(User(account), 'FULL_CONTROL')]
head_headers = \
@@ -370,8 +374,6 @@ class TestSwift3Obj(Swift3TestCase):
ACL(Owner(account, account), grants))
self.swift.register('HEAD', '/v1/AUTH_test/some/source',
head_resp, head_headers, None)
self.swift.register('PUT', '/v1/AUTH_test/bucket/object',
swob.HTTPCreated, {}, None)
put_headers = {'Authorization': 'AWS test:tester:hmac',
'X-Amz-Copy-Source': '/some/source'}
@@ -385,6 +387,22 @@ class TestSwift3Obj(Swift3TestCase):
req.content_type = 'text/plain'
return self.call_swift3(req)
@s3acl
def test_object_PUT_copy(self):
iso_format = '2014-04-01T12:00:00.000Z'
status, headers, body = \
self._test_object_PUT_copy(swob.HTTPOk)
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'], '/some/source')
self.assertEquals(headers['Content-Length'], '0')
@s3acl
def test_object_PUT_copy_headers_error(self):
etag = '7dfa07a8e59ddbcd1dc84d4c4f82aea1'
@@ -392,27 +410,27 @@ class TestSwift3Obj(Swift3TestCase):
header = {'X-Amz-Copy-Source-If-Match': etag}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPPreconditionFailed,
header)
self._test_object_PUT_copy(swob.HTTPPreconditionFailed,
header)
self.assertEquals(self._get_error_code(body), 'PreconditionFailed')
header = {'X-Amz-Copy-Source-If-None-Match': etag}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPNotModified,
header)
self._test_object_PUT_copy(swob.HTTPNotModified,
header)
self.assertEquals(self._get_error_code(body), 'PreconditionFailed')
header = {'X-Amz-Copy-Source-If-Modified-Since': last_modified_since}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPNotModified,
header)
self._test_object_PUT_copy(swob.HTTPNotModified,
header)
self.assertEquals(self._get_error_code(body), 'PreconditionFailed')
header = \
{'X-Amz-Copy-Source-If-Unmodified-Since': last_modified_since}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPPreconditionFailed,
header)
self._test_object_PUT_copy(swob.HTTPPreconditionFailed,
header)
self.assertEquals(self._get_error_code(body), 'PreconditionFailed')
def test_object_PUT_copy_headers_with_match(self):
@@ -422,7 +440,7 @@ class TestSwift3Obj(Swift3TestCase):
header = {'X-Amz-Copy-Source-If-Match': etag,
'X-Amz-Copy-Source-If-Modified-Since': last_modified_since}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPOk, header)
self._test_object_PUT_copy(swob.HTTPOk, header)
self.assertEquals(status.split()[0], '200')
self.assertEquals(len(self.swift.calls_with_headers), 2)
_, _, headers = self.swift.calls_with_headers[-1]
@@ -440,7 +458,7 @@ class TestSwift3Obj(Swift3TestCase):
header = {'X-Amz-Copy-Source-If-Match': etag,
'X-Amz-Copy-Source-If-Modified-Since': last_modified_since}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPOk, header)
self._test_object_PUT_copy(swob.HTTPOk, header)
self.assertEquals(status.split()[0], '200')
self.assertEquals(len(self.swift.calls_with_headers), 3)
@@ -463,7 +481,7 @@ class TestSwift3Obj(Swift3TestCase):
header = {'X-Amz-Copy-Source-If-None-Match': etag,
'X-Amz-Copy-Source-If-Unmodified-Since': last_modified_since}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPOk, header)
self._test_object_PUT_copy(swob.HTTPOk, header)
self.assertEquals(status.split()[0], '200')
self.assertEquals(len(self.swift.calls_with_headers), 2)
@@ -482,7 +500,7 @@ class TestSwift3Obj(Swift3TestCase):
header = {'X-Amz-Copy-Source-If-None-Match': etag,
'X-Amz-Copy-Source-If-Unmodified-Since': last_modified_since}
status, header, body = \
self._test_object_PUT_copy_headers(swob.HTTPOk, header)
self._test_object_PUT_copy(swob.HTTPOk, header)
self.assertEquals(status.split()[0], '200')
# After the check of the copy source in the case of s3acl is valid,
# Swift3 check the bucket write permissions of the destination.