Nginx原生不支持Range请求缓存,proxy_cache_range非官方指令;Range请求默认透传不缓存,需禁用proxy_force_ranges、透传Range/If-Range头、proxy_cache_bypass $http_range,并确保后端返回Accept-Ranges、Content-Range等合规响应头。

开启 proxy_cache 后,静态资源(尤其是视频、大文件、字体)的拖拽播放、分片下载或字体图标加载失败,根本原因不是缓存本身错了,而是 Nginx 默认不缓存 Range 请求,且不会基于已缓存的完整资源“合成”部分响应——它把每个 Range: bytes=xxx-yyy 请求都当作新请求透传给后端,导致重复回源、响应头错乱、甚至 200 覆盖 206,最终表现为卡顿、404、跨域字体不显示等现象。
明确 Range 请求在 proxy_cache 中的行为边界
Nginx 原生不支持“范围缓存”,proxy_cache_range 不是官方指令,macOS 或标准 Homebrew 安装的 Nginx 均不含该功能。你看到的相关配置,大概率是混淆了以下事实:
- 完整响应(无 Range 头)可被缓存:首次请求
GET /video.mp4返回 200 + 全量内容,若命中proxy_cache_valid规则,会被缓存; - Range 请求(带
Range头)默认不缓存:Nginx 不会从已缓存的完整文件中截取字节段返回,而是直接转发该 Range 请求到上游; - 即使完整资源已缓存,后续
Range请求仍显示X-Cache: MISS或BYPASS,这是正常行为,不代表配置错误。
关键配置:让 Range 请求走通,而非强行缓存
目标不是“缓存 Range”,而是确保 Range 请求能正确抵达后端、响应头合规、不被 Nginx 错误干预。核心配置如下:
-
禁用 Nginx 自主处理 Range:添加
proxy_force_ranges off;,防止 Nginx 尝试自己截取响应体; -
透传 Range 和 If-Range 头:显式设置
proxy_set_header Range $http_range;和proxy_set_header If-Range $http_if_range;; -
绕过缓存干扰:对 Range 请求跳过缓存逻辑,避免状态混乱:
proxy_cache_bypass $http_range;; -
关闭缓冲干扰:设
proxy_buffering off;,避免 Nginx 在缓冲过程中篡改Content-Range或响应码。
静态资源响应头必须兼容 Range
仅靠代理配置不够,后端(或 Nginx 直接服务静态文件时)必须返回正确的响应头,否则浏览器拒绝分片:
- 响应需含
Accept-Ranges: bytes(静态文件服务默认有,反向代理场景需确认后端返回); - 对 206 响应,必须含
Content-Range(如bytes 0-999/1234567)和准确的Content-Length(当前片段大小); - 字体类资源(.woff2/.ttf)还需跨域头支持:
Access-Control-Allow-Origin和Access-Control-Expose-Headers: Content-Length,Content-Range,否则浏览器静默拦截 Range 响应。
验证是否生效的三步检查法
别只看日志 HIT/MISS,要结合状态码与响应头判断:
- 用
curl -I -H "Range: bytes=0-1023" https://yoursite.com/file.mp4,确认返回HTTP/1.1 206 Partial Content且含Content-Range; - 对比全量请求:
curl -I https://yoursite.com/file.mp4应返回200 OK且X-Cache: HIT(说明完整资源已缓存); - 打开 Chrome DevTools → Network,播放视频并拖动进度条,观察每个请求是否为
206、Size列是否为实际字节数、Time是否明显低于首次加载——这才是真正跑通。


















