Example #1
0
 def test_check_delete_headers_removes_delete_after(self):
     ts = utils.Timestamp.now()
     headers = {'Content-Length': '0',
                'Content-Type': 'text/plain',
                'X-Delete-After': '42',
                'X-Delete-At': str(int(ts) + 40),
                'X-Timestamp': ts.internal}
     req = Request.blank('/', headers=headers)
     constraints.check_delete_headers(req)
     self.assertNotIn('X-Delete-After', req.headers)
     self.assertEqual(req.headers['X-Delete-At'], str(int(ts) + 42))
Example #2
0
 def test_check_delete_headers_removes_delete_after(self):
     ts = utils.Timestamp.now()
     headers = {'Content-Length': '0',
                'Content-Type': 'text/plain',
                'X-Delete-After': '42',
                'X-Delete-At': str(int(ts) + 40),
                'X-Timestamp': ts.internal}
     req = Request.blank('/', headers=headers)
     constraints.check_delete_headers(req)
     self.assertNotIn('X-Delete-After', req.headers)
     self.assertEqual(req.headers['X-Delete-At'], str(int(ts) + 42))
Example #3
0
    def test_check_delete_headers_sets_delete_at(self):
        ts = utils.Timestamp.now()
        expected = str(int(ts) + 1000)
        # check delete-at is passed through
        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-At': expected,
            'X-Timestamp': ts.internal
        }
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        # check delete-after is converted to delete-at
        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-After': '42',
            'X-Timestamp': ts.internal
        }
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        expected = str(int(ts) + 42)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        # check delete-after takes precedence over delete-at
        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-After': '42',
            'X-Delete-At': str(int(ts) + 40),
            'X-Timestamp': ts.internal
        }
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-After': '42',
            'X-Delete-At': str(int(ts) + 44),
            'X-Timestamp': ts.internal
        }
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)
Example #4
0
    def test_check_delete_headers_sets_delete_at(self):
        t = time.time() + 1000
        # check delete-at is passed through
        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-At': str(int(t))
        }
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        self.assertEqual(req.headers['X-Delete-At'], str(int(t)))

        # check delete-after is converted to delete-at
        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-After': '42'
        }
        req = Request.blank('/', headers=headers)
        with mock.patch('time.time', lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        expected = str(int(t) + 42)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        # check delete-after takes precedence over delete-at
        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-After': '42',
            'X-Delete-At': str(int(t) + 40)
        }
        req = Request.blank('/', headers=headers)
        with mock.patch('time.time', lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        headers = {
            'Content-Length': '0',
            'Content-Type': 'text/plain',
            'X-Delete-After': '42',
            'X-Delete-At': str(int(t) + 44)
        }
        req = Request.blank('/', headers=headers)
        with mock.patch('time.time', lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)
Example #5
0
    def test_check_delete_headers_sets_delete_at(self):
        ts = utils.Timestamp.now()
        expected = str(int(ts) + 1000)
        # check delete-at is passed through
        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-At': expected,
                   'X-Timestamp': ts.internal}
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        # check delete-after is converted to delete-at
        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-After': '42',
                   'X-Timestamp': ts.internal}
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        expected = str(int(ts) + 42)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        # check delete-after takes precedence over delete-at
        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-After': '42',
                   'X-Delete-At': str(int(ts) + 40),
                   'X-Timestamp': ts.internal}
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-After': '42',
                   'X-Delete-At': str(int(ts) + 44),
                   'X-Timestamp': ts.internal}
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertIn('X-Delete-At', req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)
    def test_check_delete_headers_sets_delete_at(self):
        t = time.time() + 1000
        # check delete-at is passed through
        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-At': str(int(t))}
        req = Request.blank('/', headers=headers)
        constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        self.assertEqual(req.headers['X-Delete-At'], str(int(t)))

        # check delete-after is converted to delete-at
        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-After': '42'}
        req = Request.blank('/', headers=headers)
        with mock.patch('time.time', lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        expected = str(int(t) + 42)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        # check delete-after takes precedence over delete-at
        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-After': '42',
                   'X-Delete-At': str(int(t) + 40)}
        req = Request.blank('/', headers=headers)
        with mock.patch('time.time', lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)

        headers = {'Content-Length': '0',
                   'Content-Type': 'text/plain',
                   'X-Delete-After': '42',
                   'X-Delete-At': str(int(t) + 44)}
        req = Request.blank('/', headers=headers)
        with mock.patch('time.time', lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue('X-Delete-At' in req.headers)
        self.assertEqual(req.headers['X-Delete-At'], expected)
    def test_check_delete_headers_sets_delete_at(self):
        t = time.time() + 1000
        # check delete-at is passed through
        headers = {"Content-Length": "0", "Content-Type": "text/plain", "X-Delete-At": str(int(t))}
        req = Request.blank("/", headers=headers)
        constraints.check_delete_headers(req)
        self.assertTrue("X-Delete-At" in req.headers)
        self.assertEqual(req.headers["X-Delete-At"], str(int(t)))

        # check delete-after is converted to delete-at
        headers = {"Content-Length": "0", "Content-Type": "text/plain", "X-Delete-After": "42"}
        req = Request.blank("/", headers=headers)
        with mock.patch("time.time", lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue("X-Delete-At" in req.headers)
        expected = str(int(t) + 42)
        self.assertEqual(req.headers["X-Delete-At"], expected)

        # check delete-after takes precedence over delete-at
        headers = {
            "Content-Length": "0",
            "Content-Type": "text/plain",
            "X-Delete-After": "42",
            "X-Delete-At": str(int(t) + 40),
        }
        req = Request.blank("/", headers=headers)
        with mock.patch("time.time", lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue("X-Delete-At" in req.headers)
        self.assertEqual(req.headers["X-Delete-At"], expected)

        headers = {
            "Content-Length": "0",
            "Content-Type": "text/plain",
            "X-Delete-After": "42",
            "X-Delete-At": str(int(t) + 44),
        }
        req = Request.blank("/", headers=headers)
        with mock.patch("time.time", lambda: t):
            constraints.check_delete_headers(req)
        self.assertTrue("X-Delete-At" in req.headers)
        self.assertEqual(req.headers["X-Delete-At"], expected)
Example #8
0
    def _config_obj_expiration(self, req):
        delete_at_container = None
        delete_at_part = None
        delete_at_nodes = None

        req = constraints.check_delete_headers(req)

        if 'x-delete-at' in req.headers:
            x_delete_at = int(normalize_delete_at_timestamp(
                int(req.headers['x-delete-at'])))

            req.environ.setdefault('swift.log_info', []).append(
                'x-delete-at:%s' % x_delete_at)

            delete_at_container = get_expirer_container(
                x_delete_at, self.app.expiring_objects_container_divisor,
                self.account_name, self.container_name, self.object_name)

            delete_at_part, delete_at_nodes = \
                self.app.container_ring.get_nodes(
                    self.app.expiring_objects_account, delete_at_container)

        return req, delete_at_container, delete_at_part, delete_at_nodes
Example #9
0
    def _config_obj_expiration(self, req):
        delete_at_container = None
        delete_at_part = None
        delete_at_nodes = None

        req = constraints.check_delete_headers(req)

        if 'x-delete-at' in req.headers:
            x_delete_at = int(
                normalize_delete_at_timestamp(int(req.headers['x-delete-at'])))

            req.environ.setdefault('swift.log_info',
                                   []).append('x-delete-at:%s' % x_delete_at)

            delete_at_container = get_expirer_container(
                x_delete_at, self.app.expiring_objects_container_divisor,
                self.account_name, self.container_name, self.object_name)

            delete_at_part, delete_at_nodes = \
                self.app.container_ring.get_nodes(
                    self.app.expiring_objects_account, delete_at_container)

        return req, delete_at_container, delete_at_part, delete_at_nodes
Example #10
0
    def test_check_delete_headers(self):
        # x-delete-at value should be relative to the request timestamp rather
        # than time.time() so separate the two to ensure the checks are robust
        ts = utils.Timestamp(time.time() + 100)

        # X-Delete-After
        headers = {'X-Delete-After': '600', 'X-Timestamp': ts.internal}
        req = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertIsInstance(req, Request)
        self.assertIn('x-delete-at', req.headers)
        self.assertNotIn('x-delete-after', req.headers)
        expected_delete_at = str(int(ts) + 600)
        self.assertEqual(req.headers.get('X-Delete-At'), expected_delete_at)

        headers = {'X-Delete-After': 'abc', 'X-Timestamp': ts.internal}

        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-After', cm.exception.body)

        headers = {'X-Delete-After': '60.1', 'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-After', cm.exception.body)

        headers = {'X-Delete-After': '-1', 'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-After in past', cm.exception.body)

        headers = {'X-Delete-After': '0', 'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-After in past', cm.exception.body)

        # x-delete-after = 0 disallowed when it results in x-delete-at equal to
        # the timestamp
        headers = {
            'X-Delete-After': '0',
            'X-Timestamp': utils.Timestamp(int(ts)).internal
        }
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-After in past', cm.exception.body)

        # X-Delete-At
        delete_at = str(int(ts) + 100)
        headers = {'X-Delete-At': delete_at, 'X-Timestamp': ts.internal}
        req = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertIsInstance(req, Request)
        self.assertIn('x-delete-at', req.headers)
        self.assertEqual(req.headers.get('X-Delete-At'), delete_at)

        headers = {'X-Delete-At': 'abc', 'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-At', cm.exception.body)

        delete_at = str(int(ts) + 100) + '.1'
        headers = {'X-Delete-At': delete_at, 'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-At', cm.exception.body)

        delete_at = str(int(ts) - 1)
        headers = {'X-Delete-At': delete_at, 'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-At in past', cm.exception.body)

        # x-delete-at disallowed when exactly equal to timestamp
        delete_at = str(int(ts))
        headers = {
            'X-Delete-At': delete_at,
            'X-Timestamp': utils.Timestamp(int(ts)).internal
        }
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-At in past', cm.exception.body)
Example #11
0
    def test_check_delete_headers(self):

        # X-Delete-After
        headers = {'X-Delete-After': '60'}
        resp = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertTrue(isinstance(resp, Request))
        self.assertTrue('x-delete-at' in resp.headers)

        headers = {'X-Delete-After': 'abc'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-After' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        headers = {'X-Delete-After': '60.1'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-After' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        headers = {'X-Delete-After': '-1'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('X-Delete-After in past' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        # X-Delete-At
        t = str(int(time.time() + 100))
        headers = {'X-Delete-At': t}
        resp = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertTrue(isinstance(resp, Request))
        self.assertTrue('x-delete-at' in resp.headers)
        self.assertEquals(resp.headers.get('X-Delete-At'), t)

        headers = {'X-Delete-At': 'abc'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-At' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time() + 100)) + '.1'
        headers = {'X-Delete-At': t}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-At' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time()))
        headers = {'X-Delete-At': t}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('X-Delete-At in past' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time() - 1))
        headers = {'X-Delete-At': t}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('X-Delete-At in past' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")
Example #12
0
    def test_check_delete_headers(self):

        # X-Delete-After
        headers = {'X-Delete-After': '60'}
        resp = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertTrue(isinstance(resp, Request))
        self.assertTrue('x-delete-at' in resp.headers)

        headers = {'X-Delete-After': 'abc'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-After' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        headers = {'X-Delete-After': '60.1'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-After' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        headers = {'X-Delete-After': '-1'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('X-Delete-After in past' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        # X-Delete-At
        t = str(int(time.time() + 100))
        headers = {'X-Delete-At': t}
        resp = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertTrue(isinstance(resp, Request))
        self.assertTrue('x-delete-at' in resp.headers)
        self.assertEquals(resp.headers.get('X-Delete-At'), t)

        headers = {'X-Delete-At': 'abc'}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-At' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time() + 100)) + '.1'
        headers = {'X-Delete-At': t}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('Non-integer X-Delete-At' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time()))
        headers = {'X-Delete-At': t}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('X-Delete-At in past' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time() - 1))
        headers = {'X-Delete-At': t}
        try:
            resp = constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue('X-Delete-At in past' in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")
Example #13
0
    def test_check_delete_headers(self):
        # x-delete-at value should be relative to the request timestamp rather
        # than time.time() so separate the two to ensure the checks are robust
        ts = time.time() + 100

        # X-Delete-After
        headers = {'X-Delete-After': '600', 'X-Timestamp': str(ts)}
        req = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertIsInstance(req, Request)
        self.assertIn('x-delete-at', req.headers)
        self.assertNotIn('x-delete-after', req.headers)
        expected_delete_at = str(int(ts) + 600)
        self.assertEqual(req.headers.get('X-Delete-At'), expected_delete_at)

        headers = {'X-Delete-After': 'abc', 'X-Timestamp': str(time.time())}

        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('Non-integer X-Delete-After', cm.exception.body)

        headers = {'X-Delete-After': '60.1', 'X-Timestamp': str(time.time())}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('Non-integer X-Delete-After', cm.exception.body)

        headers = {'X-Delete-After': '-1', 'X-Timestamp': str(time.time())}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('X-Delete-After in past', cm.exception.body)

        headers = {'X-Delete-After': '0', 'X-Timestamp': str(time.time())}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('X-Delete-After in past', cm.exception.body)

        # X-Delete-At
        delete_at = str(int(ts + 100))
        headers = {'X-Delete-At': delete_at, 'X-Timestamp': str(ts)}
        req = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertIsInstance(req, Request)
        self.assertIn('x-delete-at', req.headers)
        self.assertEqual(req.headers.get('X-Delete-At'), delete_at)

        headers = {'X-Delete-At': 'abc', 'X-Timestamp': str(ts)}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('Non-integer X-Delete-At', cm.exception.body)

        delete_at = str(int(ts + 100)) + '.1'
        headers = {'X-Delete-At': delete_at, 'X-Timestamp': str(ts)}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('Non-integer X-Delete-At', cm.exception.body)

        delete_at = str(int(ts - 1))
        headers = {'X-Delete-At': delete_at, 'X-Timestamp': str(ts)}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn('X-Delete-At in past', cm.exception.body)
    def test_check_delete_headers(self):

        # X-Delete-After
        headers = {"X-Delete-After": "60"}
        resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        self.assertTrue(isinstance(resp, Request))
        self.assertTrue("x-delete-at" in resp.headers)

        headers = {"X-Delete-After": "abc"}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("Non-integer X-Delete-After" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        headers = {"X-Delete-After": "60.1"}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("Non-integer X-Delete-After" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        headers = {"X-Delete-After": "-1"}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("X-Delete-After in past" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        # X-Delete-At
        t = str(int(time.time() + 100))
        headers = {"X-Delete-At": t}
        resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        self.assertTrue(isinstance(resp, Request))
        self.assertTrue("x-delete-at" in resp.headers)
        self.assertEquals(resp.headers.get("X-Delete-At"), t)

        headers = {"X-Delete-At": "abc"}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("Non-integer X-Delete-At" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time() + 100)) + ".1"
        headers = {"X-Delete-At": t}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("Non-integer X-Delete-At" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time()))
        headers = {"X-Delete-At": t}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("X-Delete-At in past" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")

        t = str(int(time.time() - 1))
        headers = {"X-Delete-At": t}
        try:
            resp = constraints.check_delete_headers(Request.blank("/", headers=headers))
        except HTTPException as e:
            self.assertEquals(e.status_int, HTTP_BAD_REQUEST)
            self.assertTrue("X-Delete-At in past" in e.body)
        else:
            self.fail("Should have failed with HTTPBadRequest")
Example #15
0
    def test_check_delete_headers(self):
        # x-delete-at value should be relative to the request timestamp rather
        # than time.time() so separate the two to ensure the checks are robust
        ts = utils.Timestamp(time.time() + 100)

        # X-Delete-After
        headers = {'X-Delete-After': '600',
                   'X-Timestamp': ts.internal}
        req = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertIsInstance(req, Request)
        self.assertIn('x-delete-at', req.headers)
        self.assertNotIn('x-delete-after', req.headers)
        expected_delete_at = str(int(ts) + 600)
        self.assertEqual(req.headers.get('X-Delete-At'), expected_delete_at)

        headers = {'X-Delete-After': 'abc',
                   'X-Timestamp': ts.internal}

        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-After', cm.exception.body)

        headers = {'X-Delete-After': '60.1',
                   'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-After', cm.exception.body)

        headers = {'X-Delete-After': '-1',
                   'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-After in past', cm.exception.body)

        headers = {'X-Delete-After': '0',
                   'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-After in past', cm.exception.body)

        # x-delete-after = 0 disallowed when it results in x-delete-at equal to
        # the timestamp
        headers = {'X-Delete-After': '0',
                   'X-Timestamp': utils.Timestamp(int(ts)).internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-After in past', cm.exception.body)

        # X-Delete-At
        delete_at = str(int(ts) + 100)
        headers = {'X-Delete-At': delete_at,
                   'X-Timestamp': ts.internal}
        req = constraints.check_delete_headers(
            Request.blank('/', headers=headers))
        self.assertIsInstance(req, Request)
        self.assertIn('x-delete-at', req.headers)
        self.assertEqual(req.headers.get('X-Delete-At'), delete_at)

        headers = {'X-Delete-At': 'abc',
                   'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-At', cm.exception.body)

        delete_at = str(int(ts) + 100) + '.1'
        headers = {'X-Delete-At': delete_at,
                   'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'Non-integer X-Delete-At', cm.exception.body)

        delete_at = str(int(ts) - 1)
        headers = {'X-Delete-At': delete_at,
                   'X-Timestamp': ts.internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-At in past', cm.exception.body)

        # x-delete-at disallowed when exactly equal to timestamp
        delete_at = str(int(ts))
        headers = {'X-Delete-At': delete_at,
                   'X-Timestamp': utils.Timestamp(int(ts)).internal}
        with self.assertRaises(HTTPException) as cm:
            constraints.check_delete_headers(
                Request.blank('/', headers=headers))
        self.assertEqual(cm.exception.status_int, HTTP_BAD_REQUEST)
        self.assertIn(b'X-Delete-At in past', cm.exception.body)