Merge "Ensure object copy response timestamp tags consistent with S3"
This commit is contained in:
@@ -45,6 +45,7 @@ upload information:
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
from swift.common.utils import json
|
||||
from swift.common.db import utf8encode
|
||||
@@ -120,12 +121,19 @@ class PartController(Controller):
|
||||
req.object_name = '%s/%s/%d' % (req.object_name, upload_id,
|
||||
part_number)
|
||||
|
||||
last_modified = req.check_copy_source(self.app)
|
||||
req.check_copy_source(self.app)
|
||||
resp = req.get_response(self.app)
|
||||
|
||||
if 'X-Amz-Copy-Source' in req.headers:
|
||||
obj_timestamp = (datetime.datetime.fromtimestamp(
|
||||
float(resp.environ['HTTP_X_TIMESTAMP']))
|
||||
.isoformat())
|
||||
if len(obj_timestamp) is 19:
|
||||
obj_timestamp += '.000Z'
|
||||
else:
|
||||
obj_timestamp = obj_timestamp[:-3] + 'Z'
|
||||
resp.append_copy_resp_body(req.controller_name,
|
||||
last_modified)
|
||||
obj_timestamp)
|
||||
|
||||
resp.status = 200
|
||||
return resp
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
from swift.common.http import HTTP_OK, HTTP_PARTIAL_CONTENT, HTTP_NO_CONTENT
|
||||
from swift.common.swob import Range, content_range_header_value
|
||||
@@ -95,12 +96,19 @@ class ObjectController(Controller):
|
||||
"""
|
||||
Handle PUT Object and PUT Object (Copy) request
|
||||
"""
|
||||
last_modified = req.check_copy_source(self.app)
|
||||
req.check_copy_source(self.app)
|
||||
resp = req.get_response(self.app)
|
||||
|
||||
if 'X-Amz-Copy-Source' in req.headers:
|
||||
obj_timestamp = (datetime.datetime.fromtimestamp(
|
||||
float(resp.environ['HTTP_X_TIMESTAMP']))
|
||||
.isoformat())
|
||||
if len(obj_timestamp) is 19:
|
||||
obj_timestamp += '.000Z'
|
||||
else:
|
||||
obj_timestamp = obj_timestamp[:-3] + 'Z'
|
||||
resp.append_copy_resp_body(req.controller_name,
|
||||
last_modified)
|
||||
obj_timestamp)
|
||||
|
||||
# delete object metadata from response
|
||||
for key in list(resp.headers.keys()):
|
||||
|
||||
@@ -317,9 +317,6 @@ class Request(swob.Request):
|
||||
def check_copy_source(self, app):
|
||||
"""
|
||||
check_copy_source checks the copy source existence
|
||||
|
||||
:return : last modified str if copy-source header exist
|
||||
otherwise None
|
||||
"""
|
||||
if 'X-Amz-Copy-Source' in self.headers:
|
||||
src_path = self.headers['X-Amz-Copy-Source']
|
||||
@@ -333,9 +330,6 @@ class Request(swob.Request):
|
||||
headers=headers)
|
||||
if src_resp.status_int == 304: # pylint: disable-msg=E1101
|
||||
raise PreconditionFailed()
|
||||
return src_resp.last_modified.isoformat()[:-6]
|
||||
|
||||
return None
|
||||
|
||||
def _canonical_uri(self):
|
||||
raw_path_info = self.environ.get('RAW_PATH_INFO', self.path)
|
||||
|
||||
@@ -166,7 +166,6 @@ class TestSwift3MultiUpload(Swift3FunctionalTestCase):
|
||||
self.conn.make_request('PUT', src_bucket, src_obj, body=src_content)
|
||||
_, headers, _ = self.conn.make_request('HEAD', src_bucket, src_obj)
|
||||
self.assertCommonResponseHeaders(headers)
|
||||
last_modified_date_from_header = mktime(headers['last-modified'])
|
||||
|
||||
status, headers, body, resp_etag = \
|
||||
self._upload_part_copy(src_bucket, src_obj, bucket,
|
||||
@@ -182,12 +181,20 @@ class TestSwift3MultiUpload(Swift3FunctionalTestCase):
|
||||
|
||||
last_modified = elem.find('LastModified').text
|
||||
self.assertTrue(last_modified is not None)
|
||||
last_modified_from_xml = mktime(last_modified)
|
||||
self.assertEquals(last_modified_date_from_header,
|
||||
last_modified_from_xml)
|
||||
|
||||
self.assertEquals(resp_etag, etag)
|
||||
|
||||
# Check last-modified timestamp
|
||||
key, upload_id = uploads[1]
|
||||
query = 'uploadId=%s' % upload_id
|
||||
status, headers, body = \
|
||||
self.conn.make_request('GET', bucket, key, query=query)
|
||||
|
||||
elem = fromstring(body, 'ListPartsResult')
|
||||
last_modified_get = elem.find('Part').find('LastModified').text
|
||||
self.assertEquals(last_modified_get,
|
||||
last_modified)
|
||||
|
||||
# List Parts
|
||||
key, upload_id = uploads[0]
|
||||
query = 'uploadId=%s' % upload_id
|
||||
|
||||
@@ -72,11 +72,20 @@ class TestSwift3Object(Swift3FunctionalTestCase):
|
||||
|
||||
elem = fromstring(body, 'CopyObjectResult')
|
||||
self.assertTrue(elem.find('LastModified').text is not None)
|
||||
# TODO: assert LastModified value
|
||||
last_modified_xml = elem.find('LastModified').text
|
||||
self.assertTrue(elem.find('ETag').text is not None)
|
||||
self.assertEquals(etag, elem.find('ETag').text.strip('"'))
|
||||
self._assertObjectEtag(dst_bucket, dst_obj, etag)
|
||||
|
||||
# Check timestamp on Copy:
|
||||
status, headers, body = \
|
||||
self.conn.make_request('GET', dst_bucket)
|
||||
self.assertEquals(status, 200)
|
||||
elem = fromstring(body, 'ListBucketResult')
|
||||
|
||||
self.assertEquals(elem.find('Contents').find("LastModified").text,
|
||||
last_modified_xml)
|
||||
|
||||
# GET Object
|
||||
status, headers, body = \
|
||||
self.conn.make_request('GET', self.bucket, obj)
|
||||
|
||||
@@ -1070,13 +1070,14 @@ class TestSwift3MultiUpload(Swift3TestCase):
|
||||
put_headers.update(put_header)
|
||||
req = Request.blank(
|
||||
'/bucket/object?partNumber=1&uploadId=X',
|
||||
environ={'REQUEST_METHOD': 'PUT'},
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
'HTTP_X_TIMESTAMP': '1396353600.000000'},
|
||||
headers=put_headers)
|
||||
return self.call_swift3(req)
|
||||
|
||||
@s3acl
|
||||
def test_upload_part_copy(self):
|
||||
last_modified = '2014-04-01T12:00:00'
|
||||
last_modified = '2014-04-01T12:00:00.000Z'
|
||||
status, headers, body = \
|
||||
self._test_copy_for_s3acl('test:tester')
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
|
||||
@@ -456,7 +456,8 @@ class TestSwift3Obj(Swift3TestCase):
|
||||
put_headers.update(put_header)
|
||||
|
||||
req = Request.blank('/bucket/object',
|
||||
environ={'REQUEST_METHOD': 'PUT'},
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
'HTTP_X_TIMESTAMP': '1396353600.000000'},
|
||||
headers=put_headers)
|
||||
|
||||
req.date = datetime.now()
|
||||
@@ -465,7 +466,7 @@ class TestSwift3Obj(Swift3TestCase):
|
||||
|
||||
@s3acl
|
||||
def test_object_PUT_copy(self):
|
||||
last_modified = '2014-04-01T12:00:00'
|
||||
last_modified = '2014-04-01T12:00:00.000Z'
|
||||
status, headers, body = \
|
||||
self._test_object_PUT_copy(swob.HTTPOk)
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
@@ -781,7 +782,8 @@ class TestSwift3Obj(Swift3TestCase):
|
||||
|
||||
req = Request.blank(
|
||||
'/bucket/object',
|
||||
environ={'REQUEST_METHOD': 'PUT'},
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
'HTTP_X_TIMESTAMP': '1396353600.000000'},
|
||||
headers={'Authorization': 'AWS %s:hmac' % account,
|
||||
'X-Amz-Copy-Source': src_path})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user