Ben Ramsey

HTTP Status: 206 Partial Content and Range Requests

Akki commented on my 100 Continue post, asking:

I was wondering if there was a response status to allow a large file to be “served” in parts and in just one response?

While I’ve never done this myself, I did some research to see how it might be done, and I’ve come up with a solution that I wish I could call clever, innovative, and many other words that make me sound like I came up with a smart solution, but the reality of it is that HTTP was made to support this behavior, so I’ll just tell you how to do it with standard HTTP.

First of all, let’s create a scenario. Say I want to request a very large file from a service, but before I do so, I want to find out exactly how large it is and whether the service supports “range requests.” To do this, I make a HEAD request to the large resource I want to retrieve. The HEAD method is a standard HTTP method that acts as if I’ve made a GET request, but it returns only the headers and not the body. This allows me to find out some information about the resource without actually taking the time or using the bandwidth to download it. For example, I can read the Content-Length header and determine the size of the resource.

Another header of great importance is the Accept-Ranges header. If it’s present, it may contain a value of “bytes.” If so, I know that I can make a GET request and request a byte range to retrieve only those bytes. This is the first important key component:

If you are building a service that accepts byte range requests, let clients know by providing the Accept-Ranges header in response to GET and HEAD requests.

So, now, I know I can make a range request to the service, which I do by sending a standard GET request including a Range header that specifies the range of bytes I’m requesting, like so: Range: bytes=0-999. The service should then respond with with a 206 Partial Content status code, a Content-Range header, and the requested range of bytes. This is the second key component:

If a client makes a request of your service with a Range header, return a 206 Partial Content response containing a Content-Range header and the requested range of bytes for the resource in the body. The Content-Length value should be the length of what is actually returned and not the full length of the resource.

From then on, it’s a matter of the client continuing to make requests until it has retrieved all of the bytes it wishes to get from the resource. If the client makes a range request that is out of bounds—that is, none of the range values overlap the extent of the resource—the service should respond with a 416 Requested Range Not Satisfiable status.

I should note that the service cannot force the client to make a range request. It is entirely up to the client to make such requests, so the service should honor all standard GET requests that do not contain a Range header by sending back the full representation of the requested resource. If your service allows range requests, it is to your benefit to tell the client with an Accept-Ranges header. If you want to explicitly tell the client that you do not allow range requests, send a value of “none” back with the Accept-Ranges header.

Since I learn best by looking at real-life examples, I’ll provide one for you. Here’s a real example making range requests with Flickr. I’ve removed some of the headers for simplicity and clarity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
HEAD /2390/2253727548_a413c88ab3_s.jpg HTTP/1.1
Host: farm3.static.flickr.com

HTTP/1.0 200 OK
Date: Mon, 05 May 2008 00:33:14 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 3980
Content-Type: image/jpeg

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET /2390/2253727548_a413c88ab3_s.jpg HTTP/1.1
Host: farm3.static.flickr.com
Range: bytes=0-999

HTTP/1.0 206 Partial Content
Date: Mon, 05 May 2008 00:36:57 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 1000
Content-Range: bytes 0-999/3980
Content-Type: image/jpeg

{binary data}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET /2390/2253727548_a413c88ab3_s.jpg HTTP/1.1
Host: farm3.static.flickr.com
Range: bytes=1000-

HTTP/1.0 206 Partial Content
Date: Mon, 05 May 2008 00:37:54 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 2980
Content-Range: bytes 1000-3979/3980
Content-Type: image/jpeg

{binary data}

Comments