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-9999on a 1000-byte file is0-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
Rangeheader 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 send200with the whole body. Range handling is an optimisation, and a request must never fail because of it. The unit namebytesis case-insensitive. OnlyGEThonours 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. A416carriesContent-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 usableRange):Accept-Ranges: bytes,Content-Length: <size>
Common mistakes
- A length one byte short because the end was treated as exclusive.
- Reading
-500as a negative start. - Answering 416 for a reversed or garbled range, which breaks clients that merely guessed.
- Sending the file size as
Content-Lengthon 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.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…