From c03a1b5b4b7735cc28afe830de2eaf9151a3d541 Mon Sep 17 00:00:00 2001 From: Naoto Nishizono Date: Thu, 25 Dec 2014 11:09:06 +0900 Subject: [PATCH] Fix response of Get Bucket when IsTruncated is true and delimiter is specified When IsTruncated is true and delimiter is specified, add NextMarker tag to response body. Change-Id: Ifb2c71cf232b1a5b52518ce4d61131aac730ff74 --- swift3/controllers/bucket.py | 25 ++++++++++++++++++------- swift3/test/unit/test_bucket.py | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/swift3/controllers/bucket.py b/swift3/controllers/bucket.py index 57001091..beeca09d 100644 --- a/swift3/controllers/bucket.py +++ b/swift3/controllers/bucket.py @@ -76,6 +76,20 @@ class BucketController(Controller): SubElement(elem, 'Name').text = req.container_name SubElement(elem, 'Prefix').text = req.params.get('prefix') SubElement(elem, 'Marker').text = req.params.get('marker') + + # in order to judge that truncated is valid, check whether + # max_keys + 1 th element exists in swift. + is_truncated = max_keys > 0 and len(objects) > max_keys + objects = objects[:max_keys] + + if is_truncated and 'delimiter' in req.params: + if 'name' in objects[-1]: + SubElement(elem, 'NextMarker').text = \ + objects[-1]['name'] + if 'subdir' in objects[-1]: + SubElement(elem, 'NextMarker').text = \ + objects[-1]['subdir'] + SubElement(elem, 'MaxKeys').text = str(max_keys) if 'delimiter' in req.params: @@ -84,13 +98,10 @@ class BucketController(Controller): if encoding_type is not None: SubElement(elem, 'EncodingType').text = encoding_type - if max_keys > 0 and len(objects) == max_keys + 1: - is_truncated = 'true' - else: - is_truncated = 'false' - SubElement(elem, 'IsTruncated').text = is_truncated + SubElement(elem, 'IsTruncated').text = \ + 'true' if is_truncated else 'false' - for o in objects[:max_keys]: + for o in objects: if 'subdir' not in o: contents = SubElement(elem, 'Contents') SubElement(contents, 'Key').text = o['name'] @@ -103,7 +114,7 @@ class BucketController(Controller): SubElement(owner, 'DisplayName').text = req.user_id SubElement(contents, 'StorageClass').text = 'STANDARD' - for o in objects[:max_keys]: + for o in objects: if 'subdir' in o: common_prefixes = SubElement(elem, 'CommonPrefixes') SubElement(common_prefixes, 'Prefix').text = o['subdir'] diff --git a/swift3/test/unit/test_bucket.py b/swift3/test/unit/test_bucket.py index 35f8c175..6d9f0ea2 100644 --- a/swift3/test/unit/test_bucket.py +++ b/swift3/test/unit/test_bucket.py @@ -217,6 +217,30 @@ class TestSwift3Bucket(Swift3TestCase): self.assertEquals(args['marker'], '\xef\xbc\xa2') self.assertEquals(args['prefix'], '\xef\xbc\xa3') + def test_bucket_GET_with_delimiter_max_keys(self): + bucket_name = 'junk' + req = Request.blank('/%s?delimiter=a&max-keys=2' % bucket_name, + environ={'REQUEST_METHOD': 'GET'}, + headers={'Authorization': 'AWS test:tester:hmac'}) + status, headers, body = self.call_swift3(req) + self.assertEquals(status.split()[0], '200') + elem = fromstring(body, 'ListBucketResult') + self.assertEquals(elem.find('./NextMarker').text, 'viola') + self.assertEquals(elem.find('./MaxKeys').text, '2') + self.assertEquals(elem.find('./IsTruncated').text, 'true') + + def test_bucket_GET_subdir_with_delimiter_max_keys(self): + bucket_name = 'junk_subdir' + req = Request.blank('/%s?delimiter=a&max-keys=1' % bucket_name, + environ={'REQUEST_METHOD': 'GET'}, + headers={'Authorization': 'AWS test:tester:hmac'}) + status, headers, body = self.call_swift3(req) + self.assertEquals(status.split()[0], '200') + elem = fromstring(body, 'ListBucketResult') + self.assertEquals(elem.find('./NextMarker').text, 'rose') + self.assertEquals(elem.find('./MaxKeys').text, '1') + self.assertEquals(elem.find('./IsTruncated').text, 'true') + @s3acl def test_bucket_PUT_error(self): code = self._test_method_error('PUT', '/bucket', swob.HTTPCreated,