mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-07 10:56:49 +00:00
Handle case where requested range results in empty response.
This commit is contained in:
parent
43c6af6fde
commit
69739f5f9b
@ -654,6 +654,8 @@ The ``Range`` header may be used to request exactly one ``bytes`` range, in whic
|
||||
Interpretation and response behavior is as specified in RFC 7233 § 4.1.
|
||||
Multiple ranges in a single request are *not* supported; open-ended ranges are also not supported.
|
||||
|
||||
If the response to a query is an empty range, the ``NO CONTENT`` (204) response code will be used.
|
||||
|
||||
Discussion
|
||||
``````````
|
||||
|
||||
|
@ -468,6 +468,10 @@ def read_share_chunk(
|
||||
{"range": [Range("bytes", [(offset, offset + length)]).to_header()]}
|
||||
),
|
||||
)
|
||||
|
||||
if response.code == http.NO_CONTENT:
|
||||
return b""
|
||||
|
||||
if response.code == http.PARTIAL_CONTENT:
|
||||
content_range = parse_content_range_header(
|
||||
response.headers.getRawHeaders("content-range")[0]
|
||||
@ -488,7 +492,7 @@ def read_share_chunk(
|
||||
+ f"didn't match Content-Range header ({supposed_length})"
|
||||
)
|
||||
body.seek(0)
|
||||
returnValue(body.read())
|
||||
return body.read()
|
||||
else:
|
||||
# Technically HTTP allows sending an OK with full body under these
|
||||
# circumstances, but the server is not designed to do that so we ignore
|
||||
|
@ -343,27 +343,12 @@ class _ReadRangeProducer:
|
||||
result: Deferred
|
||||
start: int
|
||||
remaining: int
|
||||
first_read: bool = field(default=True)
|
||||
|
||||
def resumeProducing(self):
|
||||
to_read = min(self.remaining, 65536)
|
||||
data = self.read_data(self.start, to_read)
|
||||
assert len(data) <= to_read
|
||||
|
||||
if self.first_read and self.remaining > 0:
|
||||
# For empty bodies the content-range header makes no sense since
|
||||
# the end of the range is inclusive. Actual conversion from
|
||||
# Python's exclusive ranges to inclusive ranges is handled by
|
||||
# werkzeug. The case where we're reading beyond the end of the
|
||||
# share is handled by the caller, read_range().
|
||||
self.request.setHeader(
|
||||
"content-range",
|
||||
ContentRange(
|
||||
"bytes", self.start, self.start + self.remaining
|
||||
).to_header(),
|
||||
)
|
||||
self.first_read = False
|
||||
|
||||
if not data and self.remaining > 0:
|
||||
d, self.result = self.result, None
|
||||
d.errback(
|
||||
@ -448,9 +433,21 @@ def read_range(
|
||||
# If we're being ask to read beyond the length of the share, just read
|
||||
# less:
|
||||
end = min(end, share_length)
|
||||
# TODO when if end is now <= offset?
|
||||
if offset >= end:
|
||||
# Basically we'd need to return an empty body. However, the
|
||||
# Content-Range header can't actually represent empty lengths... so
|
||||
# (mis)use 204 response code to indicate that.
|
||||
raise _HTTPError(http.NO_CONTENT)
|
||||
|
||||
request.setResponseCode(http.PARTIAL_CONTENT)
|
||||
|
||||
# Actual conversion from Python's exclusive ranges to inclusive ranges is
|
||||
# handled by werkzeug.
|
||||
request.setHeader(
|
||||
"content-range",
|
||||
ContentRange("bytes", offset, end).to_header(),
|
||||
)
|
||||
|
||||
d = Deferred()
|
||||
request.registerProducer(
|
||||
_ReadRangeProducer(
|
||||
|
Loading…
x
Reference in New Issue
Block a user