Merge "Make DELETE requests to expired objects return 404."
This commit is contained in:
commit
ee42e6fc72
@ -264,6 +264,15 @@ class DiskFile(object):
|
|||||||
"""
|
"""
|
||||||
return not self.data_file or 'deleted' in self.metadata
|
return not self.data_file or 'deleted' in self.metadata
|
||||||
|
|
||||||
|
def is_expired(self):
|
||||||
|
"""
|
||||||
|
Check if the file is expired.
|
||||||
|
|
||||||
|
:returns: True if the file has an X-Delete-At in the past
|
||||||
|
"""
|
||||||
|
return ('X-Delete-At' in self.metadata and
|
||||||
|
int(self.metadata['X-Delete-At']) <= time.time())
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def mkstemp(self):
|
def mkstemp(self):
|
||||||
"""Contextmanager to make a temporary file."""
|
"""Contextmanager to make a temporary file."""
|
||||||
@ -534,13 +543,8 @@ class ObjectController(object):
|
|||||||
file = DiskFile(self.devices, device, partition, account, container,
|
file = DiskFile(self.devices, device, partition, account, container,
|
||||||
obj, self.logger, disk_chunk_size=self.disk_chunk_size)
|
obj, self.logger, disk_chunk_size=self.disk_chunk_size)
|
||||||
|
|
||||||
if 'X-Delete-At' in file.metadata and \
|
if file.is_deleted() or file.is_expired():
|
||||||
int(file.metadata['X-Delete-At']) <= time.time():
|
|
||||||
return HTTPNotFound(request=request)
|
return HTTPNotFound(request=request)
|
||||||
if file.is_deleted():
|
|
||||||
response_class = HTTPNotFound
|
|
||||||
else:
|
|
||||||
response_class = HTTPAccepted
|
|
||||||
try:
|
try:
|
||||||
file_size = file.get_data_file_size()
|
file_size = file.get_data_file_size()
|
||||||
except (DiskFileError, DiskFileNotExist):
|
except (DiskFileError, DiskFileNotExist):
|
||||||
@ -563,7 +567,7 @@ class ObjectController(object):
|
|||||||
container, obj, request.headers, device)
|
container, obj, request.headers, device)
|
||||||
with file.mkstemp() as (fd, tmppath):
|
with file.mkstemp() as (fd, tmppath):
|
||||||
file.put(fd, tmppath, metadata, extension='.meta')
|
file.put(fd, tmppath, metadata, extension='.meta')
|
||||||
return response_class(request=request)
|
return HTTPAccepted(request=request)
|
||||||
|
|
||||||
@public
|
@public
|
||||||
@timing_stats
|
@timing_stats
|
||||||
@ -682,9 +686,7 @@ class ObjectController(object):
|
|||||||
obj, self.logger, keep_data_fp=True,
|
obj, self.logger, keep_data_fp=True,
|
||||||
disk_chunk_size=self.disk_chunk_size,
|
disk_chunk_size=self.disk_chunk_size,
|
||||||
iter_hook=sleep)
|
iter_hook=sleep)
|
||||||
if file.is_deleted() or \
|
if file.is_deleted() or file.is_expired():
|
||||||
('X-Delete-At' in file.metadata and
|
|
||||||
int(file.metadata['X-Delete-At']) <= time.time()):
|
|
||||||
if request.headers.get('if-match') == '*':
|
if request.headers.get('if-match') == '*':
|
||||||
return HTTPPreconditionFailed(request=request)
|
return HTTPPreconditionFailed(request=request)
|
||||||
else:
|
else:
|
||||||
@ -764,9 +766,7 @@ class ObjectController(object):
|
|||||||
return HTTPInsufficientStorage(drive=device, request=request)
|
return HTTPInsufficientStorage(drive=device, request=request)
|
||||||
file = DiskFile(self.devices, device, partition, account, container,
|
file = DiskFile(self.devices, device, partition, account, container,
|
||||||
obj, self.logger, disk_chunk_size=self.disk_chunk_size)
|
obj, self.logger, disk_chunk_size=self.disk_chunk_size)
|
||||||
if file.is_deleted() or \
|
if file.is_deleted() or file.is_expired():
|
||||||
('X-Delete-At' in file.metadata and
|
|
||||||
int(file.metadata['X-Delete-At']) <= time.time()):
|
|
||||||
return HTTPNotFound(request=request)
|
return HTTPNotFound(request=request)
|
||||||
try:
|
try:
|
||||||
file_size = file.get_data_file_size()
|
file_size = file.get_data_file_size()
|
||||||
@ -816,7 +816,7 @@ class ObjectController(object):
|
|||||||
request=request,
|
request=request,
|
||||||
body='X-If-Delete-At and X-Delete-At do not match')
|
body='X-If-Delete-At and X-Delete-At do not match')
|
||||||
orig_timestamp = file.metadata.get('X-Timestamp')
|
orig_timestamp = file.metadata.get('X-Timestamp')
|
||||||
if file.is_deleted():
|
if file.is_deleted() or file.is_expired():
|
||||||
response_class = HTTPNotFound
|
response_class = HTTPNotFound
|
||||||
metadata = {
|
metadata = {
|
||||||
'X-Timestamp': request.headers['X-Timestamp'], 'deleted': True,
|
'X-Timestamp': request.headers['X-Timestamp'], 'deleted': True,
|
||||||
|
@ -2061,6 +2061,29 @@ class TestObjectController(unittest.TestCase):
|
|||||||
finally:
|
finally:
|
||||||
object_server.time.time = orig_time
|
object_server.time.time = orig_time
|
||||||
|
|
||||||
|
def test_DELETE_but_expired(self):
|
||||||
|
test_time = time() + 10000
|
||||||
|
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
|
headers={'X-Timestamp': normalize_timestamp(test_time - 2000),
|
||||||
|
'X-Delete-At': str(int(test_time + 100)),
|
||||||
|
'Content-Length': '4',
|
||||||
|
'Content-Type': 'application/octet-stream'})
|
||||||
|
req.body = 'TEST'
|
||||||
|
resp = self.object_controller.PUT(req)
|
||||||
|
self.assertEquals(resp.status_int, 201)
|
||||||
|
|
||||||
|
orig_time = object_server.time.time
|
||||||
|
try:
|
||||||
|
t = test_time + 100
|
||||||
|
object_server.time.time = lambda: float(t)
|
||||||
|
req = Request.blank('/sda1/p/a/c/o',
|
||||||
|
environ={'REQUEST_METHOD': 'DELETE'},
|
||||||
|
headers={'X-Timestamp': normalize_timestamp(time())})
|
||||||
|
resp = self.object_controller.DELETE(req)
|
||||||
|
self.assertEquals(resp.status_int, 404)
|
||||||
|
finally:
|
||||||
|
object_server.time.time = orig_time
|
||||||
|
|
||||||
def test_DELETE_if_delete_at(self):
|
def test_DELETE_if_delete_at(self):
|
||||||
test_time = time() + 10000
|
test_time = time() + 10000
|
||||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'PUT'},
|
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user