OkHttp发起GET请求返回404 但Windows端Chrome访问同链接正常
原因分析
- 路径字符编码错位:该m3u8链接的路径段包含Base64格式的签名串,这类防盗链资源的服务端会严格匹配原始请求路径的字节流。OkHttp在默认解析字符串格式的URL时,会自动对路径中的
=这类特殊字符做URI编码(将=转为%3D),和Chrome浏览器实际发送的原始路径不一致,就会被服务端判定为非法请求返回404。 - 防盗链请求头校验:多数流媒体资源的防盗链规则会校验请求头中的User-Agent字段,OkHttp默认携带的UA为类似
okhttp/4.12.0的标识,服务端识别到非浏览器UA时,不会返回403提示,而是直接返回404隐藏校验规则,避免被轻易绕过。 - 查询串签名不匹配:该链接的
signature参数是基于固定顺序的查询串生成的校验值,如果OkHttp在解析URL时自动调整了查询参数的顺序、对参数值做了额外转码,会导致服务端计算签名时和客户端传来的串不一致,直接返回404。
对应解决方法
- 取消自动转码,构造和浏览器完全一致的路径
不要直接将字符串形式的URL传入url()方法触发自动编码逻辑,手动构造HttpUrl时,将已编码好的路径段通过encoded参数标记,避免OkHttp重复编码:val httpUrl = HttpUrl.Builder() .scheme("https") .host("www.pstream.net") // 第二个参数设为true,标记传入的路径已经是编码完成的,不再做转义 .addPathSegments( "h/480/eyJpdiI6IlFCUS9FNDFwOW9UTFJYU3BPaXJpb1E9PSIsInZhbHVlIjoiZWQ3RXlYUnhwa2F3QWZ6TDd1a0dYQT09IiwibWFjIjoiNGM0YTk5NzRlMDAwMTEwYjY5ZTRmYWIwYzk0YTMzMmQ1MWQzOTYxZWI0M2EyMGJhNTg5YTgzYzA1ODExMGE4MyJ9.m3u8", encoded = true ) // 按原始顺序添加查询参数,避免顺序错位导致签名校验失败 .addQueryParameter("expires", "1615181186") .addQueryParameter("signature", "259a1b8921d79010a91b70d76dae20e4897d3cd32c4effc5fb416cff2119b9e8") .build() - 补全对齐浏览器的请求头
在构造Request时,添加和Chrome浏览器一致的标识头,绕过UA校验:val request = Request.Builder() .url(httpUrl) .header( "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ) .build() - 抓包做差异对比
如果按照上述方法修改后依然返回404,可通过抓包工具分别获取Chrome和OkHttp发出的实际请求,逐行对比请求路径、查询串、请求头的差异,针对性修正和浏览器请求不一致的部分即可。
内容的提问来源于stack exchange,提问作者linkkader
相关产品推荐
相关产品推荐

