Skip to content
Lesson 14 of 16

Step 1 of 5 · Reading · ~4 min

Read

Caching, Compression & Beyond

Range Requests & Partial Content

A 4 GB video, a 900 MB disk image, a set of model weights: a protocol that can only say "send me the whole thing" turns every one of them into a gamble on the connection holding. Range requests are HTTP's answer. The client asks for a slice of bytes and the server sends exactly that slice. Resumable downloads, video seeking and reading a ZIP file's index without fetching the archive all fall out of one small feature. Your program will read a request, look at the resource's size and produce the exact status line and headers.

Asking for a slice

GET /movie.mp4 HTTP/1.1
Host: a.test
Range: bytes=0-1023          the first 1024 bytes
Range: bytes=1024-           from byte 1024 to the end
Range: bytes=-500            the LAST 500 bytes (a suffix range)
Range: bytes=0-499,1000-1499 two ranges

Two facts about the grammar cause nearly every bug written against it.

Both ends are inclusive. bytes=0-1023 is 1024 bytes, so a slice's length is the last byte minus the first byte plus one. Off by one does not crash. It silently drops one byte from every chunk of a resumed download, and the checksum fails long after anyone remembers why.

A leading dash is not a minus sign. In bytes=-500 the field before the dash is empty, and the number is a length: the last 500 bytes, whatever the file size is. A parser that converts the whole spec to an integer gets -500 and computes a start of minus five hundred.

Answering with a slice

HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 0-1023/45678      which bytes, and the total size
Content-Length: 1024                   the length of THIS slice, not of the file

The status is 206, not 200: that is how a client knows it holds a fragment and not a short file. Content-Range reports the slice and the total. Content-Length describes only this response, and setting it to the file size is the framing bug from the body lesson: the client waits for bytes that never arrive. Accept-Ranges: bytes on a normal 200 is the advertisement that makes the whole feature work.

What a server may repair, ignore, or refuse

RFC 9110 section 14 separates three situations.

  • Repair. An end past the last byte is clamped: 0-9999 on a 1000-byte file is 0-999. A suffix longer than the file is the whole file. The client asked for more than exists, and what exists is the useful answer.
  • Ignore. A Range header that cannot be understood must not be an error. An unknown unit (items=0-5), garbage (bytes=abc), a reversed pair (500-400), or a list of several ranges that this server chooses not to serve all mean: pretend the header was absent and send 200 with the whole body. Range handling is an optimisation, and a request must never fail because of it. The unit name bytes is case-insensitive. Only GET honours ranges.
  • Refuse. A well formed range that no byte of the resource can satisfy is 416 Range Not Satisfiable: a start at or past the end (2000- on 1000 bytes), a suffix of zero bytes (-0), or any range on an empty resource. A 416 carries Content-Range: bytes */<size>, and the * means "no slice here". The size is the point, because it tells a client working from a stale length what to ask for next.

Numbers can be absurdly long. bytes=0-99999999999999999999 must clamp like any other oversized end, not overflow an integer or crash. Treat any value too large for 18 digits as "huge".

The contract

The first input line is SIZE <n> (the resource length, LF terminated), followed by the raw request (CRLF). Print the status line, then these headers, one per line:

  • 206 Partial Content: Accept-Ranges: bytes, Content-Range: bytes <first>-<last>/<size>, Content-Length: <last - first + 1>
  • 416 Range Not Satisfiable: Content-Range: bytes */<size>
  • 200 OK (no usable Range): Accept-Ranges: bytes, Content-Length: <size>

Common mistakes

  • A length one byte short because the end was treated as exclusive.
  • Reading -500 as a negative start.
  • Answering 416 for a reversed or garbled range, which breaks clients that merely guessed.
  • Sending the file size as Content-Length on a 206.
  • Overflowing on very long numbers.

Your exercise

The starter reads the size and the headers. You parse the range, classify it as repair, ignore or refuse, and print the response head.

Up nextVirtual Hosting & the Host HeaderCaching, Compression & Beyond

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…