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:
@@ -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 =
|
||||
|
||||
@@ -53,5 +53,6 @@ class Config(dict):
|
||||
CONF = Config({
|
||||
'location': 'US',
|
||||
'max_bucket_listing': 1000,
|
||||
'max_multi_delete_objects': 1000,
|
||||
'storage_domain': '',
|
||||
})
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user