← 中文资源

简体中文版本

HTTP Range 请求头解析器

解析单段和多段字节范围,合并重叠区间,并区分语法错误与不可满足范围。

阅读英文原文

功能说明

parseRangeHeader 解析 HTTP 的 Range: bytes=... 请求头,把起止区间转换为闭区间对象,并根据资源总大小判断哪些范围有效。它支持三种形式:start-end、start- 和 -suffix,也支持逗号分隔的多段范围。返回结果用 kind 区分没有 Range 头、语法无效、范围不可满足和部分内容四种情况,方便服务端分别返回 200、忽略头、416 或 206。

解析器会丢弃超出资源末尾的不可满足范围,把合法范围的结束位置裁剪到 size - 1,并对结果排序、合并重叠或相邻区间,减少多段响应数量。它限制最多 16 段,避免恶意请求制造大量区间。

关键代码

后缀范围的长度不能超过资源大小,起点因此从 size - length 开始:

const suffix = parseInteger(spec.slice(1));
if (suffix === null || suffix === 0) {
  return { kind: "invalid", reason: `invalid suffix range "${spec}"` };
}
if (size === 0) {
  hadUnsatisfiable = true;
  continue;
}
const length = Math.min(suffix, size);
ranges.push({ start: size - length, end: size - 1 });

解析结束后若一个合法范围都不剩,返回 unsatisfiable;只要有合法范围,hadUnsatisfiable 不会影响最终结果。

使用注意

该函数只解析,不生成 Content-Range 或多段响应体;调用方需要根据返回的闭区间自行切片,并为 416 响应设置 Content-Range: bytes */size。多段范围合并后可能改变客户端请求的分段边界,但内容仍然正确;如果必须保留原始分段,应关闭合并。

语法错误和不满足范围的处理不同:未知单位、负数、起点大于终点等返回 invalid,服务端通常应忽略 Range 并返回 200;所有范围都超出资源时返回 unsatisfiable,应返回 416。大小必须是非负安全整数,否则抛 RangeError。后缀长度为 0 视为非法。超大结束值会被限制到资源末尾,但超出安全整数会判为非法。

验证方式

示例覆盖五类输入:bytes=0-499、bytes=500-、bytes=-200 分别得到对应的单段范围;bytes=0-0,900-999 得到两段;bytes=2000-3000 对 1000 字节资源返回 unsatisfiable;items=0-10 返回 invalid。可以再测试 bytes=5-2、bytes=--5 和空范围,确认都进入语法错误分支。