Merge "Let users know entity size in 416 responses"

This commit is contained in:
Jenkins 2016-12-05 19:06:45 +00:00 committed by Gerrit Code Review
commit 5084a63770
8 changed files with 41 additions and 3 deletions

View File

@ -263,7 +263,12 @@ class GetContext(WSGIContext):
byteranges = req.range.ranges_for_length(
content_length_for_swob_range)
if not byteranges:
return HTTPRequestedRangeNotSatisfiable(request=req)
headers = {'Accept-Ranges': 'bytes'}
if have_complete_listing:
headers['Content-Range'] = 'bytes */%d' % (
content_length_for_swob_range, )
return HTTPRequestedRangeNotSatisfiable(
request=req, headers=headers)
first_byte, last_byte = byteranges[0]
# For some reason, swob.Range.ranges_for_length adds 1 to the
# last byte's position.

View File

@ -1250,6 +1250,8 @@ class Response(object):
if ranges == []:
self.status = 416
close_if_possible(app_iter)
self.headers['Content-Range'] = \
'bytes */%d' % self.content_length
# Setting body + app_iter to None makes us emit the default
# body text from RESPONSE_REASONS.
body = None

View File

@ -2310,6 +2310,9 @@ class ECObjectController(BaseObjectController):
resp.headers['Content-Length'] = resp.headers.get(
'X-Object-Sysmeta-Ec-Content-Length')
resp.fix_conditional_response()
if resp.status_int == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
resp.headers['Content-Range'] = 'bytes */%s' % resp.headers[
'X-Object-Sysmeta-Ec-Content-Length']
def _make_putter(self, node, part, req, headers):
return MIMEPutter.connect(

View File

@ -135,6 +135,7 @@ class TestDlo(Base):
self.assertRaises(ResponseError, file_item.read, size=7, offset=50)
self.assert_status(416)
self.assert_header('content-range', 'bytes */50')
def test_copy(self):
# Adding a new segment, copying the manifest, and then deleting the

View File

@ -1888,8 +1888,11 @@ class TestFile(Base):
# Otherwise, the byte-range-set is unsatisfiable.
self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(416)
self.assert_header('content-range', 'bytes */%d' % file_length)
else:
self.assertEqual(file_item.read(hdrs=hdrs), data[-i:])
self.assert_header('content-range', 'bytes %d-%d/%d' % (
file_length - i, file_length - 1, file_length))
self.assert_header('etag', file_item.md5)
self.assert_header('accept-ranges', 'bytes')
@ -1903,6 +1906,7 @@ class TestFile(Base):
hdrs = {'Range': range_string}
self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(416)
self.assert_header('content-range', 'bytes */%d' % file_length)
self.assert_header('etag', file_item.md5)
self.assert_header('accept-ranges', 'bytes')
@ -2067,6 +2071,7 @@ class TestFile(Base):
self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(416)
self.assert_header('content-range', 'bytes */%d' % file_length)
def testRangedGetsWithLWSinHeader(self):
file_length = 10000

View File

@ -411,6 +411,12 @@ class TestDloGetManifest(DloTestCase):
headers={'Range': 'bytes=25-30'})
status, headers, body = self.call_dlo(req)
self.assertEqual(status, "416 Requested Range Not Satisfiable")
expected_headers = (
('Accept-Ranges', 'bytes'),
('Content-Range', 'bytes */25'),
)
for header_value_pair in expected_headers:
self.assertIn(header_value_pair, headers)
def test_get_range_many_segments_satisfiable(self):
req = swob.Request.blank('/v1/AUTH_test/mancon/manifest-many-segments',

View File

@ -1304,6 +1304,7 @@ class TestResponse(unittest.TestCase):
self.assertIn('The Range requested is not available', body)
self.assertEqual(resp.content_length, len(body))
self.assertEqual(resp.status, '416 Requested Range Not Satisfiable')
self.assertEqual(resp.content_range, 'bytes */10')
resp = swift.common.swob.Response(
body='1234567890', request=req,
@ -1321,6 +1322,7 @@ class TestResponse(unittest.TestCase):
body = ''.join(resp([], start_response))
self.assertEqual(body, '1234567890')
self.assertEqual(resp.status, '200 OK')
self.assertNotIn('Content-Range', resp.headers)
resp = swift.common.swob.Response(
body='1234567890', request=req,

View File

@ -6159,12 +6159,26 @@ class TestObjectECRangedGET(unittest.TestCase):
def test_unsatisfiable(self):
# Goes just one byte too far off the end of the object, so it's
# unsatisfiable
# unsatisfiable. This should be close enough that the object servers
# actually responded 206
obj_len = len(self.obj)
status, headers, _junk = self._get_obj(
"bytes=%d-%d" % (len(self.obj), len(self.obj) + 100))
"bytes=%d-%d" % (obj_len, obj_len + 100))
self.assertEqual(status, 416)
self.assertEqual(self.obj_etag, headers.get('Etag'))
self.assertEqual('bytes', headers.get('Accept-Ranges'))
self.assertIn('Content-Range', headers)
self.assertEqual('bytes */%d' % obj_len, headers['Content-Range'])
# Goes *way* too far off the end of the object, so we're looking at
# the (massaged) 416 from an object server
status, headers, _junk = self._get_obj(
"bytes=%d-" % (obj_len + 2 ** 30))
self.assertEqual(status, 416)
self.assertEqual(self.obj_etag, headers.get('Etag'))
self.assertEqual('bytes', headers.get('Accept-Ranges'))
self.assertIn('Content-Range', headers)
self.assertEqual('bytes */%d' % obj_len, headers['Content-Range'])
def test_off_end(self):
# Ranged GET that's mostly off the end of the object, but overlaps