Implementing HTTP 206 Partial Content support for web.py

The music player I recently blogged about required support for mp3/ogg streaming. This meant I either had to serve the actual music through apache (which was what I did at first), or adding support for this to web.py, which RCTK currently uses by default as application server.

This streaming support is defined for HTTP as Partial Content (code 206).

It turned out not to be too hard to implement. At least sufficient support for chrome to accept my streams. The code is as follows

   range = web.ctx.env.get('HTTP_RANGE')
   if range is None:
       return result

   total = len(result)
   _, r = range.split("=")
   partial_start, partial_end = r.split("-")

   start = int(partial_start)

   if not partial_end:
       end = total-1 
   else:
       end = int(partial_end)

   chunksize = (end-start)+1

   web.ctx.status = "206 Partial Content"
   web.header("Content-Range", "bytes %d-%d/%d" % (start, end, total))
   web.header("Accept-Ranges", "bytes")
   web.header("Content-Length", chunksize)
   return result[start:end+1]        

Put this in your GET method. If no range is defined, it defaults to returning the entire content. If a range is present it will find the requested range, set appropriate headers and return the correct slice.

Here is how the code is used in the RCTK application server implementation.

I suspect this implementation may not be fully bugfree but it works well enough for me. For example:

  • Should every response contain the “Accept-ranges: bytes” header to show support for partial content?
  • I suspect Chrome ending up in a loop when skipping to the end of a stream

Any improvements are, of course, welcome in the comments.

Last updated April 18, 2013, 4:35 p.m.
comments powered by Disqus