filenode.py: Fix partial HTTP Range header handling according to RFC2616

Tahoe webapi was failing on HTTP request containing a partial Range header.
This change allows movies players like mplayer to seek in movie files stored in
tahoe.

Associated tests for GET and HEAD methods are also included
This commit is contained in:
francois 2008-11-18 07:41:35 -07:00
parent ffb5985146
commit db7ad6da12
2 changed files with 35 additions and 1 deletions

View File

@ -552,6 +552,20 @@ class Web(WebMixin, testutil.StallMixin, unittest.TestCase):
d.addCallback(_got)
return d
def test_GET_FILEURL_partial_range(self):
headers = {"range": "bytes=5-"}
length = len(self.BAR_CONTENTS)
d = self.GET(self.public_url + "/foo/bar.txt", headers=headers,
return_response=True)
def _got((res, status, headers)):
self.failUnlessEqual(int(status), 206)
self.failUnless(headers.has_key("content-range"))
self.failUnlessEqual(headers["content-range"][0],
"bytes 5-%d/%d" % (length-1, length))
self.failUnlessEqual(res, self.BAR_CONTENTS[5:])
d.addCallback(_got)
return d
def test_HEAD_FILEURL_range(self):
headers = {"range": "bytes=1-10"}
d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers,
@ -565,6 +579,19 @@ class Web(WebMixin, testutil.StallMixin, unittest.TestCase):
d.addCallback(_got)
return d
def test_HEAD_FILEURL_partial_range(self):
headers = {"range": "bytes=5-"}
length = len(self.BAR_CONTENTS)
d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers,
return_response=True)
def _got((res, status, headers)):
self.failUnlessEqual(int(status), 206)
self.failUnless(headers.has_key("content-range"))
self.failUnlessEqual(headers["content-range"][0],
"bytes 5-%d/%d" % (length-1, length))
d.addCallback(_got)
return d
def test_GET_FILEURL_range_bad(self):
headers = {"range": "BOGUS=fizbop-quarnak"}
d = self.shouldFail2(error.Error, "test_GET_FILEURL_range_bad",

View File

@ -374,7 +374,14 @@ class FileDownloader(rend.Page):
start, end = bytesrange[1].split('-')
if start:
offset = int(start)
if end:
if not end:
# RFC 2616 says:
#
# "If the last-byte-pos value is absent, or if the value is
# greater than or equal to the current length of the
# entity-body, last-byte-pos is taken to be equal to one less
# than the current length of the entity- body in bytes."
end = filesize - 1
size = int(end) - offset + 1
req.setResponseCode(http.PARTIAL_CONTENT)
req.setHeader('content-range',"bytes %s-%s/%s" %