入门指南
断点续传看着成功、文件却拼坏了:Range 只对 GET 有定义,206 也只是 SHOULD
「支持断点续传」不是一个开关。Range 可以被服务端合法忽略,206 只是 SHOULD,416 也可能根本不出现,而拼装只有在同一份强校验器下才安全。讲清 Range、Content-Range 与 If-Range 各自约束谁,以及「只取一部分」为什么比整份下载更容易出事故。
能不能拼,取决于这几段是不是同一份表示。

先看答案
- 适合谁
- 把「支持断点续传」写进产品介绍、却没核过服务端行为的人
- 做下载器、视频播放或大文件分发,遇到「拼出来是坏的」的人
- 看到 206 就以为一切正常、没有比对过校验器的人
- 你会获得
- 先分清谁在承诺,再谈能不能拼。
- 发布时间
- 实质更新
- 发布
- AOPC 编辑部
60 秒结论
一分钟看懂这篇文章
能不能拼,取决于这几段是不是同一份表示。
人负责
- 判断该不该承诺「支持断点续传」
- 分清是服务端没实现还是客户端拼错了
AI 负责
- 读 206 的 Content-Range 三个数
- 用 If-Range 复现一次降级为 200
- 发 Range 请求
- 读状态码与 Content-Range
- 核对强校验器
- 按同一份拼装
直接答案
「我明明支持断点续传,用户下下来的文件却是坏的。」
这句话里通常混着三件不同的事:服务端愿不愿意只发一部分、它有没有说清发的是哪一部分、客户端凭什么认为这几段能拼在一起。规范对这三件事的约束强度完全不同:一件是 MAY,一件是 SHOULD,只有第三件是 MUST。
| 你看到的 | 字面意思 | 不能推出什么 |
|---|---|---|
200 + 完整内容 |
服务端忽略了 Range,或本来就不支持 |
不能推出「服务端坏了」——忽略是明确允许的 |
206 + Content-Range |
这次只发了某一段,并声明了是哪一段 | 不能推出「你请求的区间都发了」 |
416 + Content-Range: bytes */N |
你请求的区间一个都不可满足 | 不能推出「服务端一定会回 416」 |
304 |
条件请求命中,Range 根本没参与 |
不能推出「内容没变」(见另篇) |
四条硬规则,先记住:
Range只在GET上有定义。原文:For this specification, GET is the only method for which range handling is defined.- 服务端可以合法忽略它。原文:
A server MAY ignore the Range header field. 206是SHOULD,不是MUST。原文:the server SHOULD send a 206 (Partial Content) response。- 拼装的前提是同一份强校验器,这一条才是
MUST级别的要求,也是「拼坏了」最常见的成因。
一、Range 是请求,不是承诺
Range 的语义很窄:它请求「只传选中表示的一个或多个子区间」。原文:
The “Range” header field on a GET request modifies the method semantics to request transfer of only one or more subranges of the selected representation data, rather than the entire selected representation.
注意主语是请求。同一个 §14.2 里紧接着给了服务端一条明确的豁免:
A server MAY ignore the Range header field. However, origin servers and intermediate caches ought to support byte ranges when possible, since they support efficient recovery from partially failed transfers and partial retrieval of large representations.
ought to 是建议,不是义务。所以「我的服务端支持 Range」这句话,在规范层面只能由你对自己那台服务端的实测来支撑,不能由「HTTP 支持 Range」推出来。
而且「说不认识就不理」是被强制规定的,只是方向不同:
A server MUST ignore a Range header field received with a request method that is unrecognized or for which range handling is not defined.
An origin server MUST ignore a Range header field that contains a range unit it does not understand. A proxy MAY discard a Range header field that contains a range unit it does not understand.
源站是 MUST ignore,代理是 MAY discard。也就是说,一个不认识的单位(不是 bytes)在经过中间层时,可能在源站看到之前就消失了。
还有一组「可以不干」的情形,值得抄进排错笔记:
A server that supports range requests MAY ignore or reject a Range header field that contains an invalid ranges-specifier (Section 14.1.1), a ranges-specifier with more than two overlapping ranges, or a set of many small ranges that are not listed in ascending order, since these are indications of either a broken client or a deliberate denial-of-service attack (Section 17.15).
以及零长度表示:
A server that supports range requests MAY ignore a Range header field when the selected representation has no content (i.e., the selected representation’s data is of zero length).
这条很容易被忽略:一个 0 字节文件的 Range: bytes=0-,服务端可以完全不甩你。
二、区间怎么算:从 0 开始、含首含尾、按编码后的字节算
bytes 单位的定义有三处细节,任何一处理解错都会让「取第 N 段」偏一位:
The first-pos value in a bytes int-range gives the offset of the first byte in a range. The last-pos value gives the offset of the last byte in the range; that is, the byte positions specified are inclusive. Byte offsets start at zero.
含首含尾、从 0 开始。所以 bytes=0-499 是 500 个字节,不是 499 个。
If the representation data has a content coding applied, each byte range is calculated with respect to the encoded sequence of bytes, not the sequence of underlying bytes that would be obtained after decoding.
压缩过的表示,偏移是按压缩后的字节算的。这一条直接决定了「先 gzip 再切片」和「先切片再 gzip」是两种完全不同的东西。
两条边界规则:
If the last-pos value is absent, or if the value is greater than or equal to the current length of the representation data, the byte range is interpreted as the remainder of the representation (i.e., the server replaces the value of last-pos with a value that is one less than the current length of the selected representation).
A client can refer to the last N bytes (N > 0) of the selected representation using a suffix-range. If the selected representation is shorter than the specified suffix-length, the entire representation is used.
所以 bytes=500-99999 在一个 1234 字节的文件上等价于 bytes=500-1233,而 bytes=-500 在同一个文件上给的是最后 500 字节。这两种写法都不会报错——它们会被静默地解释成另一个区间。这是「我请求的和你给的不是一回事,但谁都没报错」的第一种来源。
「可满足」也有精确定义,对 bytes 是两条:
For a GET request, a valid bytes range-spec is satisfiable if it is either: an int-range with a first-pos that is less than the current length of the selected representation or a suffix-range with a non-zero suffix-length.
When a selected representation has zero length, the only satisfiable form of range-spec in a GET request is a suffix-range with a non-zero suffix-length.
注意第一条:只要 first-pos 小于当前长度就算可满足,哪怕 first-pos 落在文件中间、你要的那段根本不存在。
三、206 是 SHOULD,416 也可能不来
规范给 206 的前提条件写得很长,结尾是 SHOULD:
If all of the preconditions are true, the server supports the Range header field for the target resource, the received Range field-value contains a valid ranges-specifier with a range-unit supported for that target resource, and that ranges-specifier is satisfiable with respect to the selected representation, the server SHOULD send a 206 (Partial Content) response with content containing one or more partial representations that correspond to the satisfiable range-spec(s) requested.
紧接着还有一句几乎总被忽略的话:
The above does not imply that a server will send all requested ranges. In some cases, it may only be possible (or efficient) to send a portion of the requested ranges first, while expecting the client to re-request the remaining portions later if they are still desired (see Section 15.3.7).
「回 206」不等于「你要的都给了」。 多区间请求尤其如此:规范允许服务端先发一部分,剩下的等你再要。
416 那一侧更反直觉。§15.3.8 的正文说「不可满足时就 SHOULD 回 416」,但同一节末尾带了一条注记:
Because servers are free to ignore Range, many implementations will respond with the entire selected representation in a 200 (OK) response. That is partly because most clients are prepared to receive a 200 (OK) to complete the task (albeit less efficiently) and partly because clients might not stop making an invalid range request until they have received a complete representation. Thus, clients cannot depend on receiving a 416 (Range Not Satisfiable) response even when it is most appropriate.
这句 clients cannot depend on receiving a 416 是整篇最该抄下来的句子:你写了「越界就报错」的分支,可能在线上从来没被走到过,因为对面直接给你整份文件。
206 自己还带一组必须回带的头:
A server that generates a 206 response MUST generate the following header fields, in addition to those required in the subsections below, if the field would have been sent in a 200 (OK) response to the same request: Date, Cache-Control, ETag, Expires, Content-Location, and Vary.
ETag 在这个清单里。这就是为什么「206 里没有 ETag」不是小事——下一节会看到,校验器是拼装的唯一凭据。
四、Range 什么时候压根不参与
有一条顺序规则,决定了「条件请求 + 范围请求」同时出现时的行为:
The Range header field is evaluated after evaluating the precondition header fields defined in Section 13.1, and only if the result in absence of the Range header field would be a 200 (OK) response. In other words, Range is ignored when a conditional GET would result in a 304 (Not Modified) response.
Range 在条件求值之后才算,而且只在「没有它也会是 200」时才生效。 所以一个带了 If-None-Match 的 Range 请求,可能在缓存那边直接被 304 结束,Range 从头到尾没被读过。如果你的下载器同时发这两个头,又指望「304 之后继续续传」,那是在指望一件规范没安排的事。
另一条是 If-Range 的存在前提:
A client MUST NOT generate an If-Range header field in a request that does not contain a Range header field. A server MUST ignore an If-Range header field received in a request that does not contain a Range header field.
If-Range 不是独立的条件头,它是 Range 的修饰符。单独发出去会被忽略。
五、Content-Range:三个数决定这段能不能拼
Content-Range 的语法是 range-unit SP (range-resp / unsatisfied-range),其中 range-resp = incl-range "/" (complete-length / "*")。落到 bytes 上就是三个数:起点、终点、总长。
总长那一格可以是 *:
For byte ranges, a sender SHOULD indicate the complete length of the representation from which the range has been extracted, unless the complete length is unknown or difficult to determine. An asterisk character (“*”) in place of the complete-length indicates that the representation length was unknown when the header field was generated.
* 不是「等于 0」,也不是「随便」。它是「当时不知道」。一个只拿到 Content-Range: bytes 42-1233/* 的客户端,没有任何办法确认自己拼出来的总长是对的。
两条「不许拼」的硬规则:
If a 206 (Partial Content) response contains a Content-Range header field with a range unit (Section 14.1) that the recipient does not understand, the recipient MUST NOT attempt to recombine it with a stored representation.
A Content-Range field value is invalid if it contains a range-resp that has a last-pos value less than its first-pos value, or a complete-length value less than or equal to its last-pos value. The recipient of an invalid Content-Range MUST NOT attempt to recombine the received content with a stored representation.
第二条值得逐字读:complete-length 小于或等于 last-pos 就算非法。也就是说 Content-Range: bytes 0-1233/1234 合法(最后一个字节的下标是 1233),而 bytes 0-1233/1233 非法。总长是长度,不是最大下标——差一位就整段作废。
416 那一侧:
A server generating a 416 (Range Not Satisfiable) response to a byte-range request SHOULD send a Content-Range header field with an unsatisfied-range value, as in the following example: Content-Range: bytes */1234
*/1234 里的 1234 是当前总长。文件在这期间被改过,这个数就是唯一能让你发现「我手里的旧片段对不上新文件」的线索。
六、If-Range:为什么弱校验器在这里不可用
If-Range 的作用是「省掉第二次请求」:
The “If-Range” header field allows a client to “short-circuit” the second request. Informally, its meaning is as follows: if the representation is unchanged, send me the part(s) that I am requesting in Range; otherwise, send me the entire representation.
条件为假时不是 412,而是忽略 Range、回整份 200:
A recipient of an If-Range header field MUST ignore the Range header field if the If-Range condition evaluates to false. Otherwise, the recipient SHOULD process the Range header field as requested.
这条对客户端的分支处理很关键:你等的是 206,来的可能是 200,而且这是正确行为,不是错误。
然后是这篇里最容易被违反的一条:
A client MUST NOT generate an If-Range header field containing an entity tag that is marked as weak. A client MUST NOT generate an If-Range header field containing an HTTP-date unless the client has no entity tag for the corresponding representation and the date is a strong validator in the sense defined by Section 8.8.2.2.
弱 ETag 不许用;日期只有在「没有 ETag 且这个日期是强校验器」时才许用。 很多客户端把服务器返回的 ETag 原样塞进 If-Range,如果那个值带 W/ 前缀,就已经不合规了。合规的服务端按强比较处理它,条件直接为假,于是每次都回整份 200——表现为「断点续传从来没生效过,但也没报错」。
比较方式也和另一个条件头不同:
Note that the If-Range comparison is by exact match, including when the validator is an HTTP-date, and so it differs from the “earlier than or equal to” comparison used when evaluating an If-Unmodified-Since conditional.
If-Unmodified-Since 是「早于或等于」,If-Range 是精确相等。把两者当成一回事,会在「文件在同一秒内被改过」时给出错误判断。
七、拼装只在同一份强校验器下安全
这是全篇唯一的 MUST 级结论,也是「拼出来是坏的」最直接的成因:
A response might transfer only a subrange of a representation if the connection closed prematurely or if the request used one or more Range specifications. After several such transfers, a client might have received several ranges of the same representation. These ranges can only be safely combined if they all have in common the same strong validator (Section 8.8.1).
A client that has received multiple partial responses to GET requests on a target resource MAY combine those responses into a larger continuous range if they share the same strong validator.
「同一份表示」不是靠 URL 相同来保证的,是靠强校验器相同。两份 206 的 ETag 不一致(或者压根没有 ETag),把它们拼起来在规范层面就是没有依据的操作。
合并之后的形态也有规定:
The combined response content consists of the union of partial content ranges within the new response and all of the matching stored responses. If the union consists of the entire range of the representation, then the client MUST process the combined response as if it were a complete 200 (OK) response, including a Content-Length header field that reflects the complete length. Otherwise, the client MUST process the set of continuous ranges as one of the following: an incomplete 200 (OK) response if the combined response is a prefix of the representation, a single 206 (Partial Content) response containing “multipart/byteranges” content, or multiple 206 (Partial Content) responses, each with one continuous range that is indicated by a Content-Range header field.
所以「拼完了」不等于「得到了一份完整文件」。只有并集覆盖了整个表示,才可以按 200 处理;否则它仍然是一份不完整的东西,只是可能恰好是前缀。
八、缓存那一侧的三个坑
206 是可缓存的:
A 206 response is heuristically cacheable; i.e., unless otherwise indicated by explicit cache controls (see Section 4.2.2 of [CACHING]).
缓存可以按「不完整的 200」来存它:
Likewise, a 206 (Partial Content) response MAY be stored as if it were an incomplete 200 (OK) response. However, a cache MUST NOT store incomplete or partial-content responses if it does not support the Range and Content-Range header fields or if it does not understand the range units used in those fields.
A cache MAY complete a stored incomplete response by making a subsequent range request (Section 14.2 of [HTTP]) and combining the successful response with the stored response, as defined in Section 3.4. A cache MUST NOT use an incomplete response to answer requests unless the response has been made complete, or the request is partial and specifies a range wholly within the incomplete response. A cache MUST NOT send a partial response to a client without explicitly marking it using the 206 (Partial Content) status code.
三句话拆开:
- 缓存存了半份是合法的;
- 这半份不许拿来回答任何完整请求,除非它被补全;
- 缓存不许把半份内容不标 206 就发给客户端。
第二条是「为什么有时第一次请求很慢、第二次很快」与「为什么某个边缘节点返回的内容短了一截」之间的分界线。第三条是「收到 200 但内容不全」在合规实现里不该发生的原因——真发生了,问题在中间层而不在协议。
缓存合并片段的条件比客户端更严一点:
A cache MAY combine these ranges into a single stored response, and reuse that response to satisfy later requests, if they all share the same strong validator and the cache complies with the client requirements in Section 15.3.7.3 of [HTTP].
同样是同一个强校验器。
九、十分钟核对:五组命令与判读表
下面全部用公开站点做示例,example.com 是占位域名,不对应任何真实资源。
# 1. 服务端到底认不认 Range:看有没有 Accept-Ranges,以及回的是 206 还是 200
curl -sSI https://www.example.com/big.zip | grep -iE '^(accept-ranges|content-length|etag)'
curl -sS -o /dev/null -D - -H 'Range: bytes=0-99' https://www.example.com/big.zip \
| grep -iE '^(HTTP/|content-range|content-length|etag)'
# 2. 总长与区间是不是自洽(把这三个数抄下来手算一遍)
curl -sS -o /dev/null -D - -H 'Range: bytes=100-199' https://www.example.com/big.zip \
| grep -i '^content-range'
# 3. 越界请求:看它回 416,还是干脆回整份 200
curl -sS -o /dev/null -w '%{http_code} %{size_download}\n' \
-H 'Range: bytes=999999999-' https://www.example.com/big.zip
# 4. 弱校验器进 If-Range 会怎样:先看 ETag 有没有 W/ 前缀
ETAG=$(curl -sSI https://www.example.com/big.zip | awk -F': ' 'tolower($1)=="etag"{print $2}' | tr -d '\r')
echo "ETag=$ETAG"
curl -sS -o /dev/null -D - -H "Range: bytes=0-99" -H "If-Range: $ETAG" \
https://www.example.com/big.zip | grep -iE '^(HTTP/|content-range)'
# 5. 两次取不同区间,比对它们是不是同一份
curl -sSI -H 'Range: bytes=0-99' https://www.example.com/big.zip | grep -i '^etag'
curl -sSI -H 'Range: bytes=100-199' https://www.example.com/big.zip | grep -i '^etag'
判读表:
| 看到 | 说明 | 下一步 |
|---|---|---|
请求带 Range 却回 200 + 完整长度 |
服务端忽略了它(合法) | 别在文档里承诺「支持断点续传」 |
无 Accept-Ranges: bytes |
没有声明支持字节范围 | 以实测为准,别以头为准 |
206 但无 Content-Range |
违反 §15.3.7.1 的 MUST |
查中间层有没有剥头 |
Content-Range 的 complete-length 等于 last-pos |
值非法 | 这一段按规范不能拼 |
206 无 ETag |
少了拼装凭据 | 见下节清单第 2 条 |
越界请求回 200 + 整份 |
规范明确允许 | 客户端要有这条分支 |
If-Range 带 W/ 后仍回 206 |
与 MUST ignore 不符 |
先确认服务端是不是真支持 If-Range |
两次 206 的 ETag 不同 |
期间表示变了 | 旧片段作废,别拼 |
十、上线前十二项清单
- 服务端对
GET的Range行为有实测记录(不是「框架默认支持」)。 - 每个
206都带Content-Range,且complete-length严格大于last-pos。 206回带ETag;没有ETag时,明确知道拼装没有依据。ETag是强的(无W/);弱校验器不进入If-Range。- 客户端处理「
If-Range为假 → 200 整份」这条分支。 - 客户端处理「越界 → 200 整份」这条分支,不只处理 416。
- 压缩开启时,确认切片是按编码后字节算的,或者对这类资源关掉压缩。
- 多区间请求按升序发;能不合并就不合并(每个 part 约 80 字节开销)。
- 合并片段前比对强校验器;不一致就整份重下。
- 只在前缀或不完整并集时,不把它当完整文件交付。
- 边缘节点不剥
Content-Range、不改ETag。 - 把「这条 URL 支不支持
Range」写进仓库,换人也能查。
十一、六种误读,与本周能做的五件事
误读一:「HTTP 支持 Range,所以我的服务端支持。」
原文是 MAY ignore。支持与否只能由你自己那台服务端的实测回答。
误读二:「回 206 就说明我要的区间都给了。」
原文明确 does not imply that a server will send all requested ranges,允许先发一部分。
误读三:「越界一定回 416。」
§15.3.8 的注记写着 clients cannot depend on receiving a 416,很多实现直接回整份 200。
误读四:「Content-Range 的最后一个数是最大下标。」
它是总长。bytes 0-1233/1233 是非法值,因为总长必须大于 last-pos。
误读五:「If-Range 可以用弱 ETag。」
原文是 MUST NOT。用了之后条件恒为假,每次都回整份,而你看不到任何错误。
误读六:「片段拼起来就是完整文件。」 只有并集覆盖整个表示才能按 200 处理;否则它仍是不完整的,只是可能恰好是前缀。
本周能做的五件事:
- 对一个真实大文件发一次
Range: bytes=0-99,把状态码、Content-Range、ETag三个值抄下来。 - 算一遍三个数:
last-pos - first-pos + 1应该等于这次响应的Content-Length。 - 发一次越界请求,看看你的服务端回 416 还是 200——然后把客户端的这条分支补上。
- 检查
ETag有没有W/,有的话确认代码里没有把它塞进If-Range。 - 在下载器的合并逻辑里加一句断言:两段的
ETag不同就不合并,直接整份重下。
如果只能记住一件事:Range 是请求,206 是建议,只有「同一份强校验器」是硬要求。前两件都可以被合法拒绝,第三件一旦不满足,拼出来的东西在规范层面就没有意义——而且整个过程可能一个错误码都不会出现。
边界说明:本文关于 Range、Content-Range、If-Range、206、416 与片段合并的陈述全部来自 RFC 9110 与 RFC 9111,两份来源均于 2026-11-01 访问并验证为 HTTP 200(字节数见「来源」)。不写「服务端一定支持 Range」——原文是 MAY ignore;不写「一定回 206」——原文是 SHOULD send a 206,且允许只先发部分区间;不写「If-Range 可以用弱 ETag」——原文是 MUST NOT,日期型还要求先满足强校验器;不写「Range 对 POST 也生效」——原文是 GET is the only method for which range handling is defined;不写「拼坏了就是服务端 bug」——Content-Range 缺失、单位不认识或数值非法时,接收方 MUST NOT 重组,客户端同样有责任;不写「回 416 才是正确行为」——§15.3.8 的注记明确说客户端不能依赖它。文中未给任何 CDN、对象存储或框架对 206 的具体缓存策略、分片大小默认值与并发数,也未给任何下载速度、命中率与事故时长数字。标注为编辑判断的有:第五节「*/N 是发现旧片段对不上新文件的线索」、第七节「拼完不等于完整」的表述方式、第八节三个坑的归类、第九节的命令组合与判读口径、第十节清单的顺序,以及第十一节把「弱 ETag 导致每次回整份」写成一种可观察现象(这是从 MUST NOT 与「条件为假即忽略 Range」两条规则推出的机制,未见规范原文以此措辞描述)。示例域名与 ETag 均为占位值,不对应真实站点。本文只讲「只取一部分」这件事本身;校验器是什么、304 怎么判断,见《文件改了、页面没变》一篇;预签名 URL 里 If-Range 必须进签名头的问题,见《预签名 URL 的七天不是通用上限》一篇。
来源
以下页面均于 2026-11-01 逐条访问并验证为 HTTP 200;字节数为当日抓取的实际大小。
- RFC 9110: HTTP Semantics核查于 2026/11/1(200,502 941 B):§13.1.5
If-Range的完整定义——short-circuit的口语化解释、If-Range = entity-tag / HTTP-date、不含Range时MUST NOT generate与服务端MUST ignore、MUST NOT generate an If-Range header field containing an entity tag that is marked as weak、日期型需no entity tag且为强校验器、两种求值步骤、条件为假时MUST ignore the Range header field、the If-Range comparison is by exact match与If-Unmodified-Since的差异;§14.1.1ranges-specifier语法、int-range/suffix-range/other-range、A ranges-specifier is invalid if it contains any range-spec that is invalid or undefined for the indicated range-unit;§14.1.2 字节范围的定义(含首含尾、从 0 开始、按编码后字节计算)、last-pos省略或越界按剩余部分解释、suffix-range短于表示时取整份、可满足的两条判定、零长度表示只有非零 suffix 可满足、大数解析溢出提醒;§14.2Range只修改GET语义、A server MAY ignore the Range header field、源站与代理对未知单位的差异化处理、可忽略非法/多重叠/乱序小片段、零长度可忽略、GET is the only method for which range handling is defined、Range is ignored when a conditional GET would result in a 304、the server SHOULD send a 206、does not imply that a server will send all requested ranges、不可满足时SHOULD send a 416;§14.3Accept-Ranges的语义;§14.4Content-Range语法与三种出现位置、未知单位MUST NOT attempt to recombine、*表示当时未知总长、非法值的判定(last-pos小于first-pos,或complete-length小于等于last-pos)与MUST NOT重组、416 的unsatisfied-range形态、只在 206/416 有语义;§15.3.7206定义、客户端MUST inspectContent-Type与Content-Range、MUST generate的头清单(Date, Cache-Control, ETag, Expires, Content-Location, and Vary)、Content-Length是本条消息的字节数、带If-Range时SHOULD NOT多发表示头、206是heuristically cacheable;§15.3.7.1 单片段MUST generateContent-Range;§15.3.7.2 多片段multipart/byteranges、单区间请求MUST NOT回多片段、可合并重叠区间与约 80 字节 part 开销、客户端不能依赖收到所请求的区间与顺序;§15.3.7.3These ranges can only be safely combined if they all have in common the same strong validator、合并后的三种处理形态与MUST process the combined response as if it were a complete 200 (OK) response;§15.3.8416定义、SHOULD回Content-Range: bytes */N、以及「许多实现直接回整份 200、clients cannot depend on receiving a 416」的注记。 - RFC 9111: HTTP Caching核查于 2026/11/1(200,84 477 B):§3.3
a 206 (Partial Content) response MAY be stored as if it were an incomplete 200 (OK) response、不支持Range/Content-Range或不懂其单位时MUST NOT存储、可用后续范围请求补全、MUST NOT use an incomplete response to answer requests unless ...、MUST NOT send a partial response to a client without explicitly marking it using the 206;§3.4 缓存合并片段需share the same strong validator并遵守 §15.3.7.3 的客户端要求、合并时按 §3.2 更新头部。