Handling Partial Content Requests (HTTP 206) for audio streaming
Web content streaming requires sending partial files between a server and a client, most often a web browser. This is a strict requirement for controlling audio playback using an HTML audio tag. While a simple HTTP 200 response containing the whole file will work for most use cases, it will not allow proper playback control, as is to be expected of a respectable music streaming app.
Request
First, the browser requests a partial file by including the Range
header, which encodes the position in bytes. The first word refers to the allowed range type, bytes
in our case.
bytes=
Response
Next, the server should reply that :
- it accepts file ranges, using the
Accept-Ranges: bytes
header; - it is sending an incomplete file, using the
206
HTTP status code, containing a specific number of bytes with theContent-Length
header; - and that it is sending the requested byte range, in the
Content-Range
header.
The Content-Range
header should contain the first byte index, the last, and the total file size.
Content-Range: bytes
Note that the last fragment's "end" offset should be exactly one less than the total file size.
Example
Below is a quick and dirty example for sending a partial file in python.
[code lang="python"]
if request.headers['HTTP_RANGE']:
total_size = os.path.getsize(filename)
http_range = request.headers['HTTP_RANGE']
start = int(http_range.split("=")[1].split("-")[0])
end = start + 2000000 if http_range.split("-")[1] == '' else int(http_range.split("-")[1])
if end > total_size:
end = total_size - 1
with open(filename, 'rb') as f:
f.seek(start)
body = f.read(end - start)
return Response(206, {"Content-Type": "application/octet-stream",
"Accept-Ranges": "bytes",
"Content-Range": "bytes {}-{}/{}".format(start, end, total_size)},
body)
[/code]