Fix SLO delete for accounts with non-ASCII names.

If an account contains non-ASCII characters, currently SLO delete code
will fail, as get_slo_segments() method receives a unicode object, but
UTF-8 encoded account name. Attempting to concatenate the strings fails
with a UnicodeError, as it tries to use the ASCII codec to decode the
UTF-8 encoded account name.

This patch allows accounts with non-ASCII characters in their names to
delete SLOs.

Change-Id: I619d41e62c16b25bd5f58d300a3dc71aa4dc75c2
(cherry picked from commit 0aad95005d)
This commit is contained in:
Timur Alperovich 2018-05-23 16:19:50 -07:00 committed by Tim Burke
parent c1fedb9ac5
commit 207522a00e
2 changed files with 42 additions and 2 deletions

View File

@ -1359,8 +1359,8 @@ class StaticLargeObject(object):
'%s MultipartDELETE' % new_env.get('HTTP_USER_AGENT')
new_env['swift.source'] = 'SLO'
new_env['PATH_INFO'] = (
'/%s/%s/%s' % (vrs, account, obj_name.lstrip('/'))
).encode('utf-8')
'/%s/%s/%s' % (vrs, account, obj_name.lstrip('/').encode('utf-8'))
)
resp = Request.blank('', new_env).get_response(self.app)
if resp.is_success:

View File

@ -1038,6 +1038,12 @@ class TestSloDeleteManifest(SloTestCase):
'X-Static-Large-Object': 'true'},
json.dumps([{'name': '/deltest/b_2', 'hash': 'a', 'bytes': '1'},
{'name': '/deltest/c_3', 'hash': 'b', 'bytes': '2'}]))
self.app.register(
'GET', '/v1/AUTH_test-un\xc3\xafcode/deltest/man-all-there',
swob.HTTPOk, {'Content-Type': 'application/json',
'X-Static-Large-Object': 'true'},
json.dumps([{'name': '/deltest/b_2', 'hash': 'a', 'bytes': '1'},
{'name': '/deltest/c_3', 'hash': 'b', 'bytes': '2'}]))
self.app.register(
'DELETE', '/v1/AUTH_test/deltest/man-all-there',
swob.HTTPNoContent, {}, None)
@ -1059,6 +1065,15 @@ class TestSloDeleteManifest(SloTestCase):
self.app.register(
'DELETE', '/v1/AUTH_test/deltest/d_3',
swob.HTTPNoContent, {}, None)
self.app.register(
'DELETE', '/v1/AUTH_test-un\xc3\xafcode/deltest/man-all-there',
swob.HTTPNoContent, {}, None)
self.app.register(
'DELETE', '/v1/AUTH_test-un\xc3\xafcode/deltest/b_2',
swob.HTTPNoContent, {}, None)
self.app.register(
'DELETE', '/v1/AUTH_test-un\xc3\xafcode/deltest/c_3',
swob.HTTPNoContent, {}, None)
self.app.register(
'GET', '/v1/AUTH_test/deltest/manifest-with-submanifest',
@ -1190,6 +1205,31 @@ class TestSloDeleteManifest(SloTestCase):
('DELETE', ('/v1/AUTH_test/deltest/' +
'man-all-there?multipart-manifest=delete'))]))
def test_handle_multipart_delete_non_ascii(self):
acct = u'AUTH_test-un\u00efcode'.encode('utf-8')
req = Request.blank(
'/v1/%s/deltest/man-all-there?multipart-manifest=delete' % acct,
environ={'REQUEST_METHOD': 'DELETE'})
status, _, body = self.call_slo(req)
self.assertEqual('200 OK', status)
lines = body.split('\n')
for l in lines:
parts = l.split(':')
if len(parts) == 1:
continue
key, value = parts
if key == 'Response Status':
delete_status = int(value.split()[0])
self.assertEqual(200, delete_status)
self.assertEqual(set(self.app.calls), set([
('GET',
'/v1/%s/deltest/man-all-there?multipart-manifest=get' % acct),
('DELETE', '/v1/%s/deltest/b_2?multipart-manifest=delete' % acct),
('DELETE', '/v1/%s/deltest/c_3?multipart-manifest=delete' % acct),
('DELETE', ('/v1/%s/deltest/'
'man-all-there?multipart-manifest=delete' % acct))]))
def test_handle_multipart_delete_nested(self):
req = Request.blank(
'/v1/AUTH_test/deltest/manifest-with-submanifest?' +