Change the flag set to specify bulk delete and expand archives from a HTTP

header to a query parameter.

This is needed because query parameters show up in proxy logs and headers do
not. With this change it will be easy to determine from any log line that gets
created from the original request (of which there is currently none) that the
request was a bulk action.

Note: This is not backwards compatible with the previous method of setting a
header. Because the bulk middleware has not been included in an openstack swift
release this should be fine.

Change-Id: I0297fa2de9e491bf0b8c430c0781e2e12316ed4b
This commit is contained in:
David Goetz 2013-02-07 11:11:32 -08:00
parent 9f14161455
commit 08c017418b
2 changed files with 21 additions and 19 deletions

View File

@ -49,12 +49,12 @@ class Bulk(object):
Extract Archive:
Expand tar files into a swift account. Request must be a PUT with the
header X-Extract-Archive specifying the format of archive file. Accepted
formats are tar, tar.gz, and tar.bz2.
query parameter ?extract-archive=format specifying the format of archive
file. Accepted formats are tar, tar.gz, and tar.bz2.
For a PUT to the following url:
/v1/AUTH_Account/$UPLOAD_PATH
/v1/AUTH_Account/$UPLOAD_PATH?extract-archive=tar.gz
UPLOAD_PATH is where the files will be expanded to. UPLOAD_PATH can be a
container, a pseudo-directory within a container, or an empty string. The
@ -82,7 +82,7 @@ class Bulk(object):
Bulk Delete:
Will delete multiple objects from their account with a single request.
Responds to DELETE requests with a header 'X-Bulk-Delete: true'.
Responds to DELETE requests with query parameter ?bulk-delete set.
The Content-Type should be set to text/plain. The body of the DELETE
request will be a newline separated list of url encoded objects to delete.
You can only delete 1000 (configurable) objects per request. The objects
@ -364,17 +364,16 @@ class Bulk(object):
@wsgify
def __call__(self, req):
extract_type = \
req.headers.get('X-Extract-Archive', '').lower().strip('.')
if extract_type and req.method == 'PUT':
archive_type = {'tar': '', 'tar.gz': 'gz',
'tar.bz2': 'bz2'}.get(extract_type)
extract_type = req.params.get('extract-archive')
if extract_type is not None and req.method == 'PUT':
archive_type = {
'tar': '', 'tar.gz': 'gz',
'tar.bz2': 'bz2'}.get(extract_type.lower().strip('.'))
if archive_type is not None:
return self.handle_extract(req, archive_type)
else:
return HTTPBadRequest("Unsupported archive format")
if (req.headers.get('X-Bulk-Delete', '').lower() in TRUE_VALUES and
req.method == 'DELETE'):
if 'bulk-delete' in req.params and req.method == 'DELETE':
return self.handle_delete(req)
return self.app

View File

@ -187,7 +187,7 @@ class TestUntar(unittest.TestCase):
def fake_start_response(*args, **kwargs):
pass
req = Request.blank('/tar_works/acc/cont/')
req = Request.blank('/tar_works/acc/cont/?extract-archive=tar.gz')
req.environ['wsgi.input'] = open(
os.path.join(self.testdir, 'tar_works.tar.gz'))
self.bulk(req.environ, fake_start_response)
@ -196,14 +196,17 @@ class TestUntar(unittest.TestCase):
self.app.calls = 0
req.environ['wsgi.input'] = open(
os.path.join(self.testdir, 'tar_works.tar.gz'))
req.headers['x-extract-archive'] = 'tar.gz'
req.headers['transfer-encoding'] = 'Chunked'
req.method = 'PUT'
self.bulk(req.environ, fake_start_response)
self.assertEquals(self.app.calls, 7)
self.app.calls = 0
req.headers['x-extract-archive'] = 'bad'
req = Request.blank('/tar_works/acc/cont/?extract-archive=bad')
req.method = 'PUT'
req.headers['transfer-encoding'] = 'Chunked'
req.environ['wsgi.input'] = open(
os.path.join(self.testdir, 'tar_works.tar.gz'))
t = self.bulk(req.environ, fake_start_response)
self.assertEquals(t[0], "Unsupported archive format")
@ -213,9 +216,11 @@ class TestUntar(unittest.TestCase):
tar.add(os.path.join(self.testdir, base_name))
tar.close()
self.app.calls = 0
req = Request.blank('/tar_works/acc/cont/?extract-archive=tar')
req.method = 'PUT'
req.headers['transfer-encoding'] = 'Chunked'
req.environ['wsgi.input'] = open(
os.path.join(self.testdir, 'tar_works.tar'))
req.headers['x-extract-archive'] = 'tar'
t = self.bulk(req.environ, fake_start_response)
self.assertEquals(self.app.calls, 7)
@ -434,9 +439,8 @@ class TestDelete(unittest.TestCase):
def test_bulk_delete_call(self):
def fake_start_response(*args, **kwargs):
pass
req = Request.blank('/delete_works/AUTH_Acc')
req = Request.blank('/delete_works/AUTH_Acc?bulk-delete')
req.method = 'DELETE'
req.headers['x-bulk-delete'] = 't'
req.headers['Transfer-Encoding'] = 'chunked'
req.environ['wsgi.input'] = StringIO('/c/f')
self.bulk(req.environ, fake_start_response)
@ -488,9 +492,8 @@ class TestDelete(unittest.TestCase):
def fake_start_response(*args, **kwargs):
self.assertTrue(args[0].startswith('413'))
req = Request.blank('/delete_works/AUTH_Acc')
req = Request.blank('/delete_works/AUTH_Acc?bulk-delete')
req.method = 'DELETE'
req.headers['x-bulk-delete'] = 't'
data = '\n\n' * self.bulk.max_deletes_per_request
req.environ['wsgi.input'] = StringIO(data)
req.content_length = len(data)