使用scalaj.http 2.4发送If-None-Match请求未返回304状态码问题
解决scalaj.http 2.4中If-None-Match头无法触发304响应的问题
我之前也踩过类似的坑,结合GitHub API的特性和scalaj.http的行为,主要有几个关键点需要调整:
核心问题分析
你的代码里有两个容易被忽略的细节,导致服务器没有返回预期的304:
User-Agent不符合要求或不一致:GitHub API强制要求请求必须包含有意义的
User-Agent头(比如你的GitHub用户名或应用名称)。如果两次请求的User-Agent不同,或者使用了scalaj.http的默认值(可能存在隐性变化),服务器会将其视为不同客户端的请求,不会触发缓存校验返回304。ETag值传递有误:你手动写死了ETag值,但实际应该从第一次请求的响应中直接获取并复用,确保完全匹配(包括前后的双引号)。手动输入的ETag可能和服务器返回的不一致,或者存在转义问题。
修正后的代码示例
下面是调整后的代码,确保两次请求的一致性并正确复用ETag:
import scalaj.http.Http object EtagTest extends App { // 定义统一的请求模板,保证所有固定请求头一致 val githubRequest = Http("https://api.github.com/users/octocat/orgs") .header("User-Agent", "your-github-username") // 替换成你的GitHub用户名或应用名 .header("Accept", "application/vnd.github.v3+json") // 符合GitHub API的Accept格式要求 // 第一次请求获取ETag val firstResponse = githubRequest.asString val etag = firstResponse.header("ETag").getOrElse("") println(s"获取到的ETag: $etag") // 第二次请求携带正确的If-None-Match头 val cachedResponse = githubRequest .header("If-None-Match", etag) .asString println(s"响应状态码: ${cachedResponse.code}") // 现在应该返回304 }
关键调整说明
- 统一请求头:把所有固定的请求头(
User-Agent、Accept)放到基础请求模板中,确保两次请求的头完全一致。GitHub API对Accept头也有要求,指定application/vnd.github.v3+json能避免格式差异导致的缓存失效。 - 复用ETag:直接从第一次响应中提取
ETag值,不要手动拼接或修改,这样能保证和服务器返回的校验值完全匹配。 - 验证请求一致性:如果还是有问题,可以打印两次请求的所有头信息,确认没有隐性差异:
println("第一次请求头: " + githubRequest.headers) println("第二次请求头: " + githubRequest.header("If-None-Match", etag).headers)
额外注意事项
scalaj.http 2.4版本的默认User-Agent是scalaj-http/2.4.0,虽然可以用,但GitHub更推荐使用能识别你的客户端的名称,避免被限流或拒绝请求。另外,确保你的网络环境没有代理或缓存服务器篡改请求头,这也可能导致304响应不触发。
内容的提问来源于stack exchange,提问作者Giulio Caccin
相关产品推荐
相关产品推荐

