System.Net.Http.HttpClient 缓存行为
Posted
技术标签:
【中文标题】System.Net.Http.HttpClient 缓存行为【英文标题】:System.Net.Http.HttpClient caching behavior 【发布时间】:2011-12-09 12:53:29 【问题描述】:我正在使用 NuGet 的 HttpClient 0.6.0。
我有以下 C# 代码:
var client = new HttpClient(new WebRequestHandler()
CachePolicy =
new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable)
);
client.GetAsync("http://myservice/asdf");
服务(这次是 CouchDB)返回一个 ETag 值和状态码 200 OK。返回一个值为 must-revalidate 的 Cache-Control 标头
更新,这里是来自 couchdb 的响应标头(取自 Visual Studio 调试器):
Server: CouchDB/1.1.1 (Erlang OTP/R14B04)
Etag: "1-27964df653cea4316d0acbab10fd9c04"
Date: Fri, 09 Dec 2011 11:56:07 GMT
Cache-Control: must-revalidate
下次我执行完全相同的请求时,HttpClient 会执行条件请求并返回 304 Not Modified。哪个是对的。
但是,如果我使用具有相同 CachePolicy 的低级 HttpWebRequest 类,则甚至不会第二次发出请求。这也是我希望 HttpClient 的行为方式。
是必须重新验证标头值还是为什么 HttpClient 表现不同?我只想做一个请求,然后在没有条件请求的情况下从缓存中获取其余的..
(另外,作为旁注,在调试时,响应状态代码显示为 200 OK,即使服务返回 304 Not Modified)
【问题讨论】:
缓存并非易事。你能用这两个调用的请求头更新你的帖子吗? 我认为在这种情况下请求标头不是必需的。我很困惑为什么 HttpClient 甚至会进行第二次调用(与 HttpWebRequest 相比,后者只进行一次调用)。 通常只有标头与服务器发送给您的内容有关。 哦,你的意思是响应头?我会更新那些.. 你指的 must-revalidate 标头的值是多少? 【参考方案1】:两个客户端的行为都正确。
must-revalidate
only applies to stale responses.
当缓存接收到的响应中存在 must-revalidate 指令时,该缓存不能使用条目在它变得陈旧后来响应 后续请求,而无需首先使用原始服务器重新验证它。 (即,缓存必须每次都进行端到端的重新验证,如果仅基于源服务器的 Expires 或 max-age 值,缓存的响应已过时.)
由于您没有提供明确的过期时间,caches are allowed to use heuristics to determine freshness。
由于您不提供Last-Modified
缓存do not need to warn the client that heuristics was used.
如果响应中没有出现 Expires、Cache-Control: max-age 或 Cache-Control: s-maxage(参见 14.9.3 节),并且响应中不包含其他缓存限制,缓存可以使用启发式方法计算新鲜度生命周期。如果尚未添加警告,缓存必须将警告 113 附加到任何超过 24 小时的响应。
age is calculated based on Date
header 的响应不存在,因为 Age
不存在。
如果根据启发式过期响应仍然是新鲜的,缓存可能会使用存储的响应。
一种解释是 HttpWebRequest
使用启发式算法,并且存储的响应状态码为 200 仍然是新鲜的。
【讨论】:
感谢您的正确回答。我接受了。这让我更清楚了!【参考方案2】:回答我自己的问题..
根据http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4 我想说 没有过期的“Cache-Control: must-revalidate”声明应该在每个请求上验证资源。
在这种情况下,这意味着每次生成资源时都应执行条件 GET。因此,在这种情况下,System.Net.Http.HttpClient 行为正确,而旧版 (Http)WebRequest 行为无效。
【讨论】:
这是不正确的,规范没有这么说。正确答案has been given by Hans Malherbe以上是关于System.Net.Http.HttpClient 缓存行为的主要内容,如果未能解决你的问题,请参考以下文章