Skip to content

Commit

Permalink
416 Range Not Satisfiable if requested range end > file size #1588
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay Kim committed Feb 7, 2017
1 parent cda2109 commit d741765
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ CHANGES
- Do not use readline when reading the content of a part
in the multipart reader #1535

- 416 Range Not Satisfiable if requested range end > file size #1588

- Having a `:` or `@` in a route does not work #1552

- Added `receive_timeout` timeout for websocket to receive complete message. #1325
Expand Down
9 changes: 8 additions & 1 deletion aiohttp/file_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,14 @@ def send(self, request, filepath):
count = (end or file_size) - start

if start + count > file_size:
raise HTTPRequestRangeNotSatisfiable
# rfc7233:If the last-byte-pos value is
# absent, or if the value is greater than or equal to
# the current length of the representation data,
# the byte range is interpreted as the remainder
# of the representation (i.e., the server replaces the
# value of last-byte-pos with a value that is one less than
# the current length of the selected representation).
count = file_size - start

resp = self._response_factory(status=status)
resp.content_type = ct
Expand Down
37 changes: 30 additions & 7 deletions tests/test_web_sendfile_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,36 @@ def handler(request):
assert content == b"".join(body)


@asyncio.coroutine
def test_static_file_range_end_bigger_than_size(loop, test_client, sender):
filepath = (pathlib.Path(__file__).parent / 'aiohttp.png')

@asyncio.coroutine
def handler(request):
resp = yield from sender(chunk_size=16).send(request, filepath)
return resp

app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(lambda loop: app)

with filepath.open('rb') as f:
content = f.read()

# Ensure the whole file requested in parts is correct
response = yield from client.get(
'/', headers={'Range': 'bytes=61000-62000'})

assert response.status == 206, \
"failed 'bytes=61000-62000': %s" % response.reason

body = yield from response.read()
assert len(body) == 108, \
"failed 'bytes=0-999', received %d bytes" % len(body[0])

assert content[61000:] == body


@asyncio.coroutine
def test_static_file_range_tail(loop, test_client, sender):
filepath = (pathlib.Path(__file__).parent / 'aiohttp.png')
Expand Down Expand Up @@ -408,18 +438,11 @@ def handler(request):
app.router.add_get('/', handler)
client = yield from test_client(lambda loop: app)

flen = filepath.stat().st_size

# range must be in bytes
resp = yield from client.get('/', headers={'Range': 'blocks=0-10'})
assert resp.status == 416, 'Range must be in bytes'
resp.close()

# Range end is inclusive
resp = yield from client.get('/', headers={'Range': 'bytes=0-%d' % flen})
assert resp.status == 416, 'Range end must be inclusive'
resp.close()

# start > end
resp = yield from client.get('/', headers={'Range': 'bytes=100-0'})
assert resp.status == 416, "Range start can't be greater than end"
Expand Down

0 comments on commit d741765

Please sign in to comment.