Summary

  • A byte offset says where a fragment belongs, but not which version of a representation it belongs to.
  • If-Range let one GET mean: process my Range if this strong validator still matches; otherwise ignore the range and send the whole current representation.
  • The branch avoided another request and prevented old and new bytes from being joined, while leaving range support, storage, reassembly and content correctness to separate decisions.

The suffix might belong to another object

Imagine a retrieval that stops after bytes 0 through 999,999. The client can ask for everything beginning at byte 1,000,000. If the server's representation has not changed, appending the reply is economical. If an editor inserted a paragraph near the beginning, a build replaced the archive, or content negotiation now selects different encoded bytes, the same offset points into a different sequence. A perfectly delivered suffix could produce a file that never existed on the server.

This was not merely a transport interruption. TCP could tell the application that one connection ended, but a later HTTP request opened a new exchange against a resource whose selected representation might have changed. Position and identity had to travel as separate facts. Range named the desired interval. A validator had to say whether the client's stored interval and the server's present interval were eligible to share one object.

The first standards-track HTTP/1.1 specification, RFC 2068, gave this problem a compact branch in 1997. A client with a partial entity could use Range with an ordinary condition such as If-Match. Yet if the entity had changed, the server would reject that condition and the client would need a second request for the complete current body. If-Range compressed the recovery into one exchange: return the missing part if the entity is unchanged; otherwise return the entire new entity.

RFC 2616 carried the mechanism into the 1999 HTTP/1.1 consolidation. Its two ordinary outcomes made the unusual semantics visible. When the entity tag matched, the server should provide the subrange with 206 Partial Content. When it did not match, the server should return the entire entity with 200 OK. The false condition did not make the retrieval fail. It revoked only the economy of completing the old copy.

One request carried two acceptable shapes

A typical request combined two fields:

Range: bytes=1000000-
If-Range: "version-17"

The client was not saying that a partial reply was the only acceptable result. It was saying that a partial reply was acceptable only under the named continuity condition. A match kept Range in force. A mismatch made the recipient ignore Range, so the ordinary successful GET yielded the full current selected representation.

That is why If-Range should not be flattened into the other HTTP preconditions. If-Match can prevent a method from proceeding and produce 412 Precondition Failed. If-None-Match can make a conditional GET produce 304 Not Modified. If-Range does neither. In the mismatch branch the client has already declared that the full current representation is useful. The response changes shape instead of becoming an empty refusal.

The 2014 range specification, RFC 7233, described this as short-circuiting the second request. It also narrowed the grammar's operational use. A client must not send If-Range without Range; a server ignores it when Range is absent or the target does not support ranges. If the validator matches, the server should process the range. If it does not, the server must ignore the range. Exactness resides in the branch, not in an expectation that every request will produce 206.

The current consolidation in RFC 9110 makes the evaluation order explicit. With GET, Range and If-Range, a true condition plus an applicable range leads to 206. Otherwise the range field is ignored and the response is 200. Other failures that can be detected first still take precedence. A condition cannot compel a server to support a range, turn an invalid interval into a valid one, or bypass the normal selection of a representation.

Exact bytes required a strong comparison

HTTP has both strong and weak validators because not every comparison asks the same question. Two representations may be semantically interchangeable enough for cache freshness while differing byte for byte. That looseness is useful when a client only wants to know whether displaying a cached page remains reasonable. It is unsafe when the client intends to weld a new byte interval onto stored bytes.

RFC 7232 says a strong validator changes whenever observable representation data changes and is usable for partial content ranges. A weak validator is reserved for situations where exact equality is unnecessary. Consequently, a client must not put a weak entity tag into If-Range. A Last-Modified date is permitted only when the client lacks an entity tag and the date qualifies as a strong validator.

Dates expose why that condition is strict. A resource can change twice within a clock's granularity, or an origin can emit a timestamp whose relationship to generated bytes is uncertain. If-Range compares an HTTP date exactly with the selected representation's Last-Modified value; it does not use the “earlier than or equal to” rule of If-Unmodified-Since. If the date is not strong enough, the condition is false. Saving bytes is not worth pretending that coarse time proves version continuity.

An entity tag is also opaque. The protocol does not require it to be a cryptographic digest, and a client cannot infer the generating algorithm from quotation marks. Strong comparison says that this origin will not reuse the validator across byte-different representations of this resource in the relevant period. It does not authenticate the origin, certify the file's meaning or establish equality with an object at another URL. RFC 2616 already warned that reuse of a tag across different URIs implied nothing about equivalence.

A match opened range processing, not a promise of 206

Suppose the strong tag matches. The server still has several questions to answer. Does this target support the requested range unit? Is the syntax valid? Does the interval overlap the current selected representation? Are the requested ranges reasonable to serve? If-Range decides which version branch is safe; ordinary range semantics decide whether the range can be fulfilled.

For a supported, valid and satisfiable byte range, the normal result is 206 Partial Content. A single-part response carries Content-Range, locating the returned bytes within the selected representation and giving the complete length when known. Multiple intervals use multipart/byteranges, with each part carrying its own range description. If no requested interval is satisfiable, the server can return 416 Range Not Satisfiable and report the current length.

These distinctions keep metadata from acquiring power it does not possess. Content-Range: bytes 1000000-1999999/5000000 says where one million returned bytes sit inside a five-million-byte representation. It does not say that the client's first million came from the same version. That authority comes from the shared strong validator and its comparison. Nor does a matching validator prove that the client received the entire response or wrote it correctly.

The false branch is conservative in a revealing way. A validator mismatch can cost bandwidth because the complete current representation crosses the network. But the replacement is coherent. A false positive match can be much worse: the client may silently assemble a hybrid whose prefix and suffix come from different versions. HTTP chose to make uncertain continuity expensive rather than invisible.

Caches had to preserve the same boundary

A cache may hold an incomplete 200 response, a 206 response or several disjoint ranges. That makes it a participant in assembly rather than a passive box. RFC 7234 allowed incomplete responses to be stored only by caches that understood Range and Content-Range. It allowed several ranges to be combined only if they shared the same strong validator.

The rule prevents a plausible but invalid optimization. A cache cannot take a prefix from Monday, a middle interval from Tuesday and a suffix from Wednesday merely because their coordinates cover the file without gaps. Coverage is not continuity. Every part must refer to the same selected representation version, and response metadata must be updated under the combination rules.

RFC 9111 retains this separation. A cache can complete a stored incomplete response with later range requests, but it must not use the result as complete until it has actually become complete. It must mark a partial answer as 206. It may combine ranges when the strong-validator evidence is shared. Storage, reuse and completion remain local cache responsibilities; If-Range does not perform them remotely.

This evidence model is modest but durable. The request target and selection inputs identify the resource and variant. Range records the interval requested. If-Range records the version evidence the client already holds. The server's current ETag or Last-Modified value supports the branch. The status and Content-Range describe the response. Only the client or cache can later establish that the pieces were received, assembled and retained.

The small condition kept authority distributed

The history of If-Range is easy to mistake for a convenience feature in download software. Its deeper achievement was to keep a version decision close to the actors that had the evidence. The origin generated a validator for its selected representation. The client preserved that validator with partial bytes and chose whether another interval was worth requesting. The server compared current state and selected a response shape. A cache kept its own custody record for stored parts.

No central catalogue had to assign file-version identities. No transfer service had to lock the resource until every interrupted client returned. The shared field carried only enough evidence for one next decision: may these requested bytes be treated as another part of the representation already held? A negative answer did not punish the request. It withdrew the optimization and restored a complete present copy.

The RFCs define this bargain; they do not show how a current product implements it. They cannot prove that one live ETag is strong, that an intermediary preserved it correctly, that a server actually supports ranges or that a final file reached durable storage. Those claims require request and response captures, representation-selection inputs, validator history, byte hashes and the client's assembly record.