From 1bb6563a198ac32e1d3a9937dc8699a23cf7d816 Mon Sep 17 00:00:00 2001 From: Peter Portante Date: Tue, 3 Dec 2013 13:01:15 -0500 Subject: [PATCH] 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 --- swift/obj/server.py | 20 ++++++++++++++------ test/functionalnosetests/test_object.py | 22 ++++++++++++++++++++++ test/unit/obj/test_server.py | 7 +++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/swift/obj/server.py b/swift/obj/server.py index 14b60e10e2..a5f90ef49c 100644 --- a/swift/obj/server.py +++ b/swift/obj/server.py @@ -594,13 +594,21 @@ class ObjectController(object): response_class = HTTPNoContent else: 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) + 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: self.delete_at_update('DELETE', orig_delete_at, account, container, obj, request, device) diff --git a/test/functionalnosetests/test_object.py b/test/functionalnosetests/test_object.py index 97cd8d0f26..dad8635da9 100755 --- a/test/functionalnosetests/test_object.py +++ b/test/functionalnosetests/test_object.py @@ -581,6 +581,28 @@ class TestObject(unittest.TestCase): self.assertEquals(resp.getheader('Content-Type'), '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): if skip: raise SkipTest diff --git a/test/unit/obj/test_server.py b/test/unit/obj/test_server.py index 078557df45..fb25f12abb 100755 --- a/test/unit/obj/test_server.py +++ b/test/unit/obj/test_server.py @@ -2840,6 +2840,13 @@ class TestObjectController(unittest.TestCase): resp = req.get_response(self.object_controller) 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): given_args = []