Handle non-integer values for if-delete-at

If a client passes us a non-integer value for if-delete-at we'll now
properly report a 400 error instead of a 503.

Closes-Bug: 1259300
Change-Id: I8bb0bb9aa158d415d4f491b5802048f0cd4d8ef6
This commit is contained in:
Peter Portante 2013-12-03 13:01:15 -05:00
parent f3f437ffb9
commit 1bb6563a19
3 changed files with 43 additions and 6 deletions

View File

@ -594,13 +594,21 @@ class ObjectController(object):
response_class = HTTPNoContent response_class = HTTPNoContent
else: else:
response_class = HTTPConflict response_class = HTTPConflict
if 'x-if-delete-at' in request.headers and \
int(request.headers['x-if-delete-at']) != \
int(orig_metadata.get('X-Delete-At') or 0):
return HTTPPreconditionFailed(
request=request,
body='X-If-Delete-At and X-Delete-At do not match')
orig_delete_at = int(orig_metadata.get('X-Delete-At') or 0) orig_delete_at = int(orig_metadata.get('X-Delete-At') or 0)
try:
req_if_delete_at_val = request.headers['x-if-delete-at']
req_if_delete_at = int(req_if_delete_at_val)
except KeyError:
pass
except ValueError:
return HTTPBadRequest(
request=request,
body='Bad X-If-Delete-At header value')
else:
if orig_delete_at != req_if_delete_at:
return HTTPPreconditionFailed(
request=request,
body='X-If-Delete-At and X-Delete-At do not match')
if orig_delete_at: if orig_delete_at:
self.delete_at_update('DELETE', orig_delete_at, account, self.delete_at_update('DELETE', orig_delete_at, account,
container, obj, request, device) container, obj, request, device)

View File

@ -581,6 +581,28 @@ class TestObject(unittest.TestCase):
self.assertEquals(resp.getheader('Content-Type'), self.assertEquals(resp.getheader('Content-Type'),
'text/html; charset=UTF-8') 'text/html; charset=UTF-8')
def test_delete_if_delete_at_bad(self):
if skip:
raise SkipTest
def put(url, token, parsed, conn):
conn.request('PUT',
'%s/%s/hi-delete-bad' % (parsed.path, self.container),
'there', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(put)
resp.read()
self.assertEquals(resp.status, 201)
def delete(url, token, parsed, conn):
conn.request('DELETE', '%s/%s/hi' % (parsed.path, self.container),
'', {'X-Auth-Token': token,
'X-If-Delete-At': 'bad'})
return check_response(conn)
resp = retry(delete)
resp.read()
self.assertEquals(resp.status, 400)
def test_null_name(self): def test_null_name(self):
if skip: if skip:
raise SkipTest raise SkipTest

View File

@ -2840,6 +2840,13 @@ class TestObjectController(unittest.TestCase):
resp = req.get_response(self.object_controller) resp = req.get_response(self.object_controller)
self.assertEquals(resp.status_int, 204) self.assertEquals(resp.status_int, 204)
req = Request.blank(
'/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'DELETE'},
headers={'X-Timestamp': normalize_timestamp(test_time - 92),
'X-If-Delete-At': 'abc'})
resp = req.get_response(self.object_controller)
self.assertEquals(resp.status_int, 400)
def test_DELETE_calls_delete_at(self): def test_DELETE_calls_delete_at(self):
given_args = [] given_args = []