新手搞懂,为什么同样 M3U8,浏览器打开和 curl 返回内容会不一样
一、很多开发会遇到的迷惑现象不少同学拿到一条 M3U8 地址用 curl 命令请求返回完整的清单文本HTTP 状态码 200看起来一切正常。但是复制到浏览器网页播放直接黑屏、403甚至拿到的 M3U8 文本内容和 curl 返回的不完全一样。很多人第一反应是地址被篡改或者工具 BUG。实际上 curl 是单纯的 HTTP 客户端浏览器除了发 HTTP 请求还会携带 Cookie、Origin、Referer还会触发 CORS 跨域校验、CDN 的浏览器识别逻辑。CDN、WAF 防火墙可以根据请求头区分是 curl 脚本访问还是真实浏览器访问返回不同结果。很多线上问题就是这样脚本拨测全部绿灯真实用户浏览器访问大量报错。如果只依靠 curl 做自动化拨测会漏掉大量真实浏览器环境才会出现的隐患。遇到这类 curl 正常、浏览器异常的现象我会使用 m3u8live.cn在真实浏览器环境加载这条 M3U8查看浏览器实际拿到的原始 M3U8 文本对比 curl 返回结果快速定位差异点。二、curl 和浏览器返回结果不一致的常见原因1.WAF、CDN 对 UA 用户代理做识别拦截curl 默认 UA 字符串很简单部分 WAF、CDN 会把 curl 识别为爬虫脚本直接做限制。有可能 curl 返回 200浏览器正常 UA 反而返回 403也有可能反过来curl 被拦截浏览器可以正常访问。2. 请求头 Origin、Referer 带来鉴权差异防盗链、鉴权逻辑读取 Referer、Origin 请求头。curl 默认不带 Origin浏览器访问会自动带上。鉴权规则依赖这些头字段就会出现两者访问结果不一样。3.Cookie 会话信息差异浏览器会自动带上域名对应的 Cookiecurl 默认不带 Cookie。如果鉴权逻辑依赖 Cookie 校验两者返回结果就会完全不同。4.CDN 缓存差异化响应CDN 根据客户端 UA 做缓存curl 拿到的是一份缓存版本浏览器命中另外一份缓存M3U8 清单文本内容出现差异。5.OPTIONS 预检请求的影响浏览器发送跨域请求先发送 OPTIONS 预检curl 不会发送 OPTIONS。服务端如果对 OPTIONS 做特殊拦截浏览器整体请求失败curl 不受影响。三、简单的排查步骤第一步分别用 curl 获取 M3U8 文本再把同一个链接粘贴网页调试工具查看浏览器实际获取的原始 M3U8 内容。把两份文本做对比看内容、长度是否一致。第二步复制浏览器 F12 网络面板里面完整的请求头UA、Referer、Origin、Cookie给 curl 带上一模一样的请求头再测试。带上浏览器全套请求头之后curl 结果和浏览器保持一致说明是请求头差异导致问题带上之后依旧不一样排查 CDN/WAF 的特征识别策略。第三步观察浏览器控制台重点看 CORS、OPTIONS 预检请求状态。重要提醒curl 只能做 HTTP 层粗粒度拨测不能替代真实浏览器环境的验证。四、开发测试避坑提醒线上自动化拨测脚本不能只用默认 curl需要模拟浏览器全套请求头尽量贴近真实用户访问行为。拨测脚本全部返回 200不代表真实网页浏览器播放一定正常。出现 curl 正常浏览器异常优先对比两套环境完整请求头再看返回的 M3U8 原始文本差异。五、总结curl 命令和浏览器拿到 M3U8 返回结果不一样是生产环境并不少见的现象。UA、Referer、Origin、Cookie、WAF 识别、OPTIONS 预检都会造成访问结果差异。不要把 curl 的返回结果当做网页业务的最终判断标准。借助网页调试工具拿到浏览器真实返回的 M3U8 原始文本和 curl 结果做对比就可以快速定位两者差异解决这类迷惑问题。