功能说明
该示例解析下载与视频播放常用的 Range 请求头,只处理规范允许的单段形式 bytes=start-end。它区分三种写法:普通区间、开放结尾,以及从末尾计数的后缀形式。解析结果包含起始、结束字节与长度,或以 unsatisfiable 标记该范围不可满足。
关键代码
正则同时捕获两段,允许任一端为空以表达开放或后缀。后缀形式里 0 是非法的,单独处理。结尾为空时取资源最后一个字节;随后统一检查起点是否大于终点、起点是否越界,并对终点做上界截断。长度计算用截断后的终点,避免返回超出资源的长度。输入缺失时返回 null 表示没有范围请求,与不可满足区分开。
使用注意
多段范围在真实请求中少见且实现复杂,本示例明确只支持单段,遇到不匹配即视为不可满足,调用方应回以 416 与 Content-Range 头说明当前长度。资源大小为 0 时任何范围都不可满足。解析器不处理 If-Range 条件,需要时应先校验 ETag 或日期再决定是否回退为完整响应,否则可能向已变动的资源返回过期字节。
代码示例
export function parseRange(header, size) {
if (!header || typeof header !== 'string') return null;
const match = /^bytes=(\d*)-(\d*)$/.exec(header.trim());
if (!match) return { unsatisfiable: true };
const [, startRaw, endRaw] = match;
if (startRaw === '' && endRaw === '') return { unsatisfiable: true };
let start;
let end;
if (startRaw === '') {
const suffix = Number(endRaw);
if (suffix === 0) return { unsatisfiable: true };
start = Math.max(size - suffix, 0);
end = size - 1;
} else {
start = Number(startRaw);
end = endRaw === '' ? size - 1 : Number(endRaw);
}
if (start > end || start >= size) return { unsatisfiable: true };
return { start, end: Math.min(end, size - 1), length: Math.min(end, size - 1) - start + 1 };
}