Fix download resumption for new SLOs.

SLOs created after commit 2d25fe6ad3
have an explicit X-Object-Sysmeta-SLO-Size attribute. Fetching one of
those with a range like "bytes=100-" would crash and cause a 500. This
commit fixes the crash.

Closes-Bug: #1656147

Change-Id: I174ed98b4f01a5943af12177d6f8c3586f049778
This commit is contained in:
Samuel Merritt 2017-01-12 13:42:57 -08:00 committed by Clay Gerrard
parent 7f6d316dd6
commit 0590d20fcc
3 changed files with 40 additions and 1 deletions

View File

@ -703,7 +703,9 @@ class SloGetContext(WSGIContext):
if lheader == SYSMETA_SLO_ETAG:
slo_etag = value
elif lheader == SYSMETA_SLO_SIZE:
content_length = value
# it's from sysmeta, so we don't worry about non-integer
# values here
content_length = int(value)
elif lheader not in ('etag', 'content-length'):
response_headers.append((header, value))

View File

@ -354,6 +354,33 @@ class TestSlo(Base):
self.assertEqual('b', file_contents[-2])
self.assertEqual('c', file_contents[-1])
def test_slo_ranged_get_half_open_on_right(self):
file_item = self.env.container.file('manifest-abcde')
file_contents = file_item.read(
hdrs={"Range": "bytes=1048571-"})
grouped_file_contents = [
(char, sum(1 for _char in grp))
for char, grp in itertools.groupby(file_contents)]
self.assertEqual([
('a', 5),
('b', 1048576),
('c', 1048576),
('d', 1048576),
('e', 1)
], grouped_file_contents)
def test_slo_ranged_get_half_open_on_left(self):
file_item = self.env.container.file('manifest-abcde')
file_contents = file_item.read(
hdrs={"Range": "bytes=-123456"})
grouped_file_contents = [
(char, sum(1 for _char in grp))
for char, grp in itertools.groupby(file_contents)]
self.assertEqual([
('d', 123455),
('e', 1),
], grouped_file_contents)
def test_slo_multi_ranged_get(self):
file_item = self.env.container.file('manifest-abcde')
file_contents = file_item.read(

View File

@ -3017,6 +3017,16 @@ class TestSloConditionalGetOldManifest(SloTestCase):
self.assertNotIn('X-Backend-Etag-Is-At', self.app.headers[0])
self.assertNotIn('X-Backend-Etag-Is-At', self.app.headers[1])
def test_range_resume_download(self):
req = Request.blank(
'/v1/AUTH_test/gettest/manifest-abcd',
environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=20-'})
status, headers, body = self.call_slo(req)
self.assertEqual(status, '206 Partial Content')
self.assertEqual(body, 'ccccccccccdddddddddddddddddddd')
class TestSloConditionalGetNewManifest(TestSloConditionalGetOldManifest):
def setUp(self):