diff --git a/swift/common/middleware/listing_formats.py b/swift/common/middleware/listing_formats.py
index 7803462679..d70ac484e5 100644
--- a/swift/common/middleware/listing_formats.py
+++ b/swift/common/middleware/listing_formats.py
@@ -55,12 +55,23 @@ def get_listing_content_type(req):
out_content_type = req.accept.best_match(
['text/plain', 'application/json', 'application/xml', 'text/xml'])
except ValueError:
- raise HTTPBadRequest(request=req, body='Invalid Accept header')
+ raise HTTPBadRequest(request=req, body=b'Invalid Accept header')
if not out_content_type:
raise HTTPNotAcceptable(request=req)
return out_content_type
+def to_xml(document_element):
+ result = tostring(document_element, encoding='UTF-8').replace(
+ b"",
+ b'', 1)
+ if not result.startswith(b'\n' + result
+ return result
+
+
def account_to_xml(listing, account_name):
if isinstance(account_name, bytes):
account_name = account_name.decode('utf-8')
@@ -76,9 +87,7 @@ def account_to_xml(listing, account_name):
SubElement(sub, field).text = six.text_type(
record.pop(field))
sub.tail = '\n'
- return tostring(doc, encoding='UTF-8').replace(
- b"",
- b'', 1)
+ return to_xml(doc)
def container_to_xml(listing, base_name):
@@ -96,10 +105,7 @@ def container_to_xml(listing, base_name):
'last_modified'):
SubElement(sub, field).text = six.text_type(
record.pop(field))
-
- return tostring(doc, encoding='UTF-8').replace(
- b"",
- b'', 1)
+ return to_xml(doc)
def listing_to_text(listing):
diff --git a/test/unit/common/middleware/test_listing_formats.py b/test/unit/common/middleware/test_listing_formats.py
index d140026b8f..6ac6d08735 100644
--- a/test/unit/common/middleware/test_listing_formats.py
+++ b/test/unit/common/middleware/test_listing_formats.py
@@ -29,13 +29,13 @@ class TestListingFormats(unittest.TestCase):
{'name': 'bar', 'bytes': 0, 'count': 0,
'last_modified': '1970-01-01T00:00:00.000000'},
{'subdir': 'foo_'},
- ])
+ ]).encode('ascii')
self.fake_container_listing = json.dumps([
{'name': 'bar', 'hash': 'etag', 'bytes': 0,
'content_type': 'text/plain',
'last_modified': '1970-01-01T00:00:00.000000'},
{'subdir': 'foo/'},
- ])
+ ]).encode('ascii')
def test_valid_account(self):
self.fake_swift.register('GET', '/v1/a', HTTPOk, {
@@ -44,7 +44,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a')
resp = req.get_response(self.app)
- self.assertEqual(resp.body, 'bar\nfoo_\n')
+ self.assertEqual(resp.body, b'bar\nfoo_\n')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -52,7 +52,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a?format=txt')
resp = req.get_response(self.app)
- self.assertEqual(resp.body, 'bar\nfoo_\n')
+ self.assertEqual(resp.body, b'bar\nfoo_\n')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -68,14 +68,14 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a?format=xml')
resp = req.get_response(self.app)
- self.assertEqual(resp.body.split('\n'), [
- '',
- '',
- 'bar00'
- '1970-01-01T00:00:00.000000'
- '',
- '',
- '',
+ self.assertEqual(resp.body.split(b'\n'), [
+ b'',
+ b'',
+ b'bar00'
+ b'1970-01-01T00:00:00.000000'
+ b'',
+ b'',
+ b'',
])
self.assertEqual(resp.headers['Content-Type'],
'application/xml; charset=utf-8')
@@ -89,7 +89,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a/c')
resp = req.get_response(self.app)
- self.assertEqual(resp.body, 'bar\nfoo/\n')
+ self.assertEqual(resp.body, b'bar\nfoo/\n')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -97,7 +97,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a/c?format=txt')
resp = req.get_response(self.app)
- self.assertEqual(resp.body, 'bar\nfoo/\n')
+ self.assertEqual(resp.body, b'bar\nfoo/\n')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -115,14 +115,14 @@ class TestListingFormats(unittest.TestCase):
resp = req.get_response(self.app)
self.assertEqual(
resp.body,
- '\n'
- ''
- ''
- 'foo/'
- ''
+ b'\n'
+ b''
+ b''
+ b'foo/'
+ b''
)
self.assertEqual(resp.headers['Content-Type'],
'application/xml; charset=utf-8')
@@ -131,12 +131,12 @@ class TestListingFormats(unittest.TestCase):
def test_blank_account(self):
self.fake_swift.register('GET', '/v1/a', HTTPOk, {
- 'Content-Length': '2', 'Content-Type': 'application/json'}, '[]')
+ 'Content-Length': '2', 'Content-Type': 'application/json'}, b'[]')
req = Request.blank('/v1/a')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '204 No Content')
- self.assertEqual(resp.body, '')
+ self.assertEqual(resp.body, b'')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -145,7 +145,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a?format=txt')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '204 No Content')
- self.assertEqual(resp.body, '')
+ self.assertEqual(resp.body, b'')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -154,7 +154,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a?format=json')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '200 OK')
- self.assertEqual(resp.body, '[]')
+ self.assertEqual(resp.body, b'[]')
self.assertEqual(resp.headers['Content-Type'],
'application/json; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -163,10 +163,10 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a?format=xml')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '200 OK')
- self.assertEqual(resp.body.split('\n'), [
- '',
- '',
- '',
+ self.assertEqual(resp.body.split(b'\n'), [
+ b'',
+ b'',
+ b'',
])
self.assertEqual(resp.headers['Content-Type'],
'application/xml; charset=utf-8')
@@ -175,12 +175,12 @@ class TestListingFormats(unittest.TestCase):
def test_blank_container(self):
self.fake_swift.register('GET', '/v1/a/c', HTTPOk, {
- 'Content-Length': '2', 'Content-Type': 'application/json'}, '[]')
+ 'Content-Length': '2', 'Content-Type': 'application/json'}, b'[]')
req = Request.blank('/v1/a/c')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '204 No Content')
- self.assertEqual(resp.body, '')
+ self.assertEqual(resp.body, b'')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -189,7 +189,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a/c?format=txt')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '204 No Content')
- self.assertEqual(resp.body, '')
+ self.assertEqual(resp.body, b'')
self.assertEqual(resp.headers['Content-Type'],
'text/plain; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -198,7 +198,7 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a/c?format=json')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '200 OK')
- self.assertEqual(resp.body, '[]')
+ self.assertEqual(resp.body, b'[]')
self.assertEqual(resp.headers['Content-Type'],
'application/json; charset=utf-8')
self.assertEqual(self.fake_swift.calls[-1], (
@@ -207,9 +207,9 @@ class TestListingFormats(unittest.TestCase):
req = Request.blank('/v1/a/c?format=xml')
resp = req.get_response(self.app)
self.assertEqual(resp.status, '200 OK')
- self.assertEqual(resp.body.split('\n'), [
- '',
- '',
+ self.assertEqual(resp.body.split(b'\n'), [
+ b'',
+ b'',
])
self.assertEqual(resp.headers['Content-Type'],
'application/xml; charset=utf-8')
@@ -236,7 +236,7 @@ class TestListingFormats(unittest.TestCase):
do_test('/v1/a/c/o')
def test_static_web_not_json(self):
- body = 'doesnt matter'
+ body = b'doesnt matter'
self.fake_swift.register(
'GET', '/v1/staticweb/not-json', HTTPOk,
{'Content-Length': str(len(body)),
@@ -253,7 +253,7 @@ class TestListingFormats(unittest.TestCase):
# FakeSwift seems to make this hard to do
def test_static_web_not_really_json(self):
- body = 'raises ValueError'
+ body = b'raises ValueError'
self.fake_swift.register(
'GET', '/v1/staticweb/not-json', HTTPOk,
{'Content-Length': str(len(body)),
@@ -272,7 +272,7 @@ class TestListingFormats(unittest.TestCase):
'content_type': 'text/plain',
'last_modified': '1970-01-01T00:00:00.000000'},
{'subdir': 'foo/'},
- ] * 160000)
+ ] * 160000).encode('ascii')
self.assertGreater( # sanity
len(body), listing_formats.MAX_CONTAINER_LISTING_CONTENT_LENGTH)
@@ -291,7 +291,7 @@ class TestListingFormats(unittest.TestCase):
def test_static_web_bad_json(self):
def do_test(body_obj):
- body = json.dumps(body_obj)
+ body = json.dumps(body_obj).encode('ascii')
self.fake_swift.register(
'GET', '/v1/staticweb/bad-json', HTTPOk,
{'Content-Length': str(len(body)),
@@ -322,7 +322,7 @@ class TestListingFormats(unittest.TestCase):
do_test(['some string'])
def test_static_web_bad_but_not_terrible_json(self):
- body = json.dumps([{'no name': 'nor subdir'}])
+ body = json.dumps([{'no name': 'nor subdir'}]).encode('ascii')
self.fake_swift.register(
'GET', '/v1/staticweb/bad-json', HTTPOk,
{'Content-Length': str(len(body)),
diff --git a/tox.ini b/tox.ini
index bec2e7cf85..b562252c11 100644
--- a/tox.ini
+++ b/tox.ini
@@ -42,6 +42,7 @@ commands =
test/unit/common/middleware/test_gatekeeper.py \
test/unit/common/middleware/test_healthcheck.py \
test/unit/common/middleware/test_list_endpoints.py \
+ test/unit/common/middleware/test_listing_formats.py \
test/unit/common/middleware/test_proxy_logging.py \
test/unit/common/ring \
test/unit/common/test_base_storage_server.py \