<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Downloads · XB 现场笔记</title><link>https://www.xbcatm.com/zh/tags/downloads/</link><description>基于 HTTP、DNS、TLS、Caddy、SSH、发布与恢复的可复现运维现场笔记。</description><generator>Hugo</generator><language>zh-CN</language><atom:link href="https://www.xbcatm.com/zh/tags/downloads/index.xml" rel="self" type="application/rss+xml"/><item><title>范围请求应证明选中了哪些字节</title><link>https://www.xbcatm.com/zh/notes/range-requests-should-prove-which-bytes-were-selected/</link><pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.xbcatm.com/zh/notes/range-requests-should-prove-which-bytes-were-selected/</guid><description>验证部分响应、Content-Range，以及无法满足的字节范围的行为。</description><content:encoded>&lt;p&gt;范围请求让客户端请求表示的一部分。媒体播放器、可断点续传的下载工具与诊断客户端会用到它，但服务器如果错误地声明或返回范围，就可能产生静默损坏，而不是干净的失败。&lt;/p&gt;
&lt;h3 id="建立完整大小"&gt;建立完整大小&lt;/h3&gt;
&lt;p&gt;抓取完整表示的响应头，并记录其长度与验证器：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://www.example.test/downloads/archive.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -sS -D full.headers -o /dev/null &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;tolower($1) ~ /^(content-length:|etag:|last-modified:|accept-ranges:)$/ { print }&amp;#39;&lt;/span&gt; full.headers
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Accept-Ranges: bytes&lt;/code&gt; 是显式信号，但缺少这个头并不能证明范围请求不受支持。去实际请求一次。&lt;/p&gt;
&lt;h3 id="请求一个已知区间"&gt;请求一个已知区间&lt;/h3&gt;
&lt;p&gt;请求开头 16 字节，同时保留响应头与正文：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -sS -D range.headers -o range.body &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s1"&gt;&amp;#39;Range: bytes=0-15&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wc -c range.body
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;awk &lt;span class="s1"&gt;&amp;#39;tolower($1) ~ /^(content-range:|content-length:|etag:)$/ || /^HTTP\// { print }&amp;#39;&lt;/span&gt; range.headers
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;成功的字节范围响应应使用 &lt;code&gt;206 Partial Content&lt;/code&gt;。&lt;code&gt;Content-Range&lt;/code&gt; 应指出 &lt;code&gt;0-15&lt;/code&gt; 与完整表示长度，而正文应正好包含 16 个字节。&lt;/p&gt;
&lt;h3 id="测试一个不可能的区间"&gt;测试一个不可能的区间&lt;/h3&gt;
&lt;p&gt;请求超出已知末尾的字节：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -sS -D - -o /dev/null &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s1"&gt;&amp;#39;Range: bytes=999999999-&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对无法满足的字节范围，&lt;code&gt;416 Range Not Satisfiable&lt;/code&gt; 加一个类似 &lt;code&gt;bytes */12345&lt;/code&gt; 的 &lt;code&gt;Content-Range&lt;/code&gt; 值会暴露真实长度。当服务器忽略 Range 时返回 &lt;code&gt;200&lt;/code&gt; 也可能合法，但它必须返回完整表示，而不是一个标签错误的片段。&lt;/p&gt;
&lt;h3 id="让验证器留在故事里"&gt;让验证器留在故事里&lt;/h3&gt;
&lt;p&gt;续传工具可以用 &lt;code&gt;If-Range&lt;/code&gt; 配合强验证器或日期。如果表示已改变，安全响应是完整的最新表示，而不是从两个版本拼接出的字节。在宣称某个下载&amp;quot;可续传&amp;quot;之前，先测试这一行为。&lt;/p&gt;
&lt;h2 id="来源"&gt;来源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-range-requests"&gt;RFC 9110 — HTTP Semantics&lt;/a&gt;，范围单位、部分响应与 &lt;code&gt;Content-Range&lt;/code&gt;，已核验 2026-08-23。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://curl.se/docs/manpage.html"&gt;curl manual&lt;/a&gt;，&lt;code&gt;--range&lt;/code&gt; 与响应头选项，已核验 2026-08-23。&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>