multi_delete: limit the maximum number of objects

This introduces a config value to limit the maximum number of objects we can
delete with a multi delete request.  The default value is same as S3's one.

Change-Id: I77d404e43ba8532cbf81c680dcb82ec69b8f31cc
This commit is contained in:
MORITA Kazutaka
2014-08-12 00:43:07 +09:00
parent 151031372c
commit 94f900f03a
4 changed files with 39 additions and 6 deletions

View File

@@ -33,6 +33,10 @@ use = egg:swift3#swift3
# response.
# max_bucket_listing = 1000
#
# Set the maximum number of objects we can delete with the Multi-Object Delete
# operation.
# max_multi_delete_objects = 1000
#
# Specify a host name of your Swift cluster. This enables virtual-hosted style
# requests.
# storage_domain =

View File

@@ -53,5 +53,6 @@ class Config(dict):
CONF = Config({
'location': 'US',
'max_bucket_listing': 1000,
'max_multi_delete_objects': 1000,
'storage_domain': '',
})

View File

@@ -18,6 +18,8 @@ from swift3.etree import Element, SubElement, fromstring, tostring, \
XMLSyntaxError, DocumentInvalid
from swift3.response import HTTPOk, S3NotImplemented, NoSuchKey, \
ErrorResponse, MalformedXML
from swift3.cfg import CONF
from swift3.utils import LOGGER
MAX_MULTI_DELETE_BODY_SIZE = 61365
@@ -33,10 +35,7 @@ class MultiObjectDeleteController(Controller):
Handles Delete Multiple Objects.
"""
def object_key_iter(xml):
try:
elem = fromstring(xml, 'Delete')
except (XMLSyntaxError, DocumentInvalid):
raise MalformedXML()
elem = fromstring(xml, 'Delete')
for obj in elem.iterchildren('Object'):
key = obj.find('./Key').text
@@ -48,8 +47,20 @@ class MultiObjectDeleteController(Controller):
elem = Element('DeleteResult')
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
for key, version in object_key_iter(xml):
try:
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
delete_list = list(object_key_iter(xml))
if len(delete_list) > CONF.max_multi_delete_objects:
raise MalformedXML()
except (XMLSyntaxError, DocumentInvalid):
raise MalformedXML()
except ErrorResponse:
raise
except Exception as e:
LOGGER.error(e)
raise
for key, version in delete_list:
if version is not None:
# TODO: delete the specific version of the object
raise S3NotImplemented()

View File

@@ -22,6 +22,7 @@ from swift.common.swob import Request
from swift3.test.unit import Swift3TestCase
from swift3.etree import tostring, Element, SubElement
from swift3.cfg import CONF
class TestSwift3MultiDelete(Swift3TestCase):
@@ -97,5 +98,21 @@ class TestSwift3MultiDelete(Swift3TestCase):
status, headers, body = self.call_swift3(req)
self.assertEquals(self._get_error_code(body), 'InvalidRequest')
def test_object_multi_DELETE_too_many_keys(self):
elem = Element('Delete')
for i in range(CONF.max_multi_delete_objects + 1):
obj = SubElement(elem, 'Object')
SubElement(obj, 'Key').text = str(i)
body = tostring(elem, use_s3ns=False)
content_md5 = md5(body).digest().encode('base64').strip()
req = Request.blank('/bucket?delete',
environ={'REQUEST_METHOD': 'POST'},
headers={'Authorization': 'AWS test:tester:hmac',
'Content-MD5': content_md5},
body=body)
status, headers, body = self.call_swift3(req)
self.assertEquals(self._get_error_code(body), 'MalformedXML')
if __name__ == '__main__':
unittest.main()