#2507·sanic

Range requests get wrong data when using file_stream()

Author: jfyang2010Created Jul 28, 2022Updated Sep 12, 2026

Describe the bug when stream_large_files=True, app.static() responses with more data than expected when doing some range-requests that the range size is not aligned to the chunk size. It's due to file_steam() and a fix is shown as below.

Code snippet with

from sanic import Sanic
app = Sanic("try")
app.static("/view", "srv", use_content_range=True, stream_large_files=True)
app.run(host="0.0.0.0", port=8000)
bash
curl -r 0-5000 localhost:8000/view/big.file | wc -c

shows 8192 as the final count.

Expected behavior A count of 5001 is expected instead.

Reasoning and fix It's due to the _streaming_fn() in file_stream() in response.py.

As the following diff shows, the buggy code is reading min((_range.size, chunk_size)) bytes, which is fixed, in the streaming loop. For a full read, it's okey to get an empty string at the end; while in range-requests, it may read and return more across the end boundary.

By changing _range.size to to_send the bug is fixed.

diff
--- response.a.py	2022-07-28 19:03:48.575385670 +0800
+++ response.b.py	2022-07-28 19:05:24.756010839 +0800
@@ -488,7 +488,7 @@
                 await f.seek(_range.start)
                 to_send = _range.size
                 while to_send > 0:
-                    content = await f.read(min((_range.size, chunk_size)))
+                    content = await f.read(min((to_send, chunk_size)))
                     if len(content) < 1:
                         break
                     to_send -= len(content)

Environment (please complete the following information):

  • OS: Linux
  • Version: 22.3.2