简体   繁体   English

System.Net.Http.HttpClient 缓存行为

[英]System.Net.Http.HttpClient caching behavior

I'm using HttpClient 0.6.0 from NuGet.我正在使用 NuGet 的 HttpClient 0.6.0。

I have the following C# code:我有以下 C# 代码:

var client = new HttpClient(new WebRequestHandler() {
    CachePolicy =
        new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable)
});
client.GetAsync("http://myservice/asdf");

The service (this time CouchDB) returns an ETag value and status code 200 OK.该服务(这次是 CouchDB)返回一个 ETag 值和状态代码 200 OK。 There is returned a Cache-Control header with value must-revalidate返回一个 Cache-Control 标头,其值为 must-revalidate

Update, here are the response headers from couchdb (taken from the visual studio debugger):更新,这里是来自 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

Next time I do the exact same request, HttpClient does a conditional request and gets back 304 Not Modified.下次我执行完全相同的请求时,HttpClient 执行条件请求并返回 304 Not Modified。 Which is right.哪个是对的。

However, if I am using low-level HttpWebRequest class with the same CachePolicy, the request isn't even made the second time.但是,如果我使用具有相同 CachePolicy 的低级 HttpWebRequest 类,则该请求甚至不会第二次发出。 This is the way I would want HttpClient also behave.这是我希望 HttpClient 也表现的方式。

Is it the must-revalidate header value or why is HttpClient behaving differently?是必须重新验证标头值还是 HttpClient 的行为不同? I would like to do only one request and then have the rest from cache without the conditional request..我只想做一个请求,然后在没有条件请求的情况下从缓存中获取其余请求。

(Also, as a side-note, when debugging, the Response status code is shown as 200 OK, even though the service returns 304 Not Modified) (另外,作为旁注,调试时,响应状态代码显示为 200 OK,即使服务返回 304 Not Modified)

Both clients behave correctly.两个客户端的行为都正确。

must-revalidate only applies to stale responses . must-revalidate仅适用于陈旧的响应

When the must-revalidate directive is present in a response received by a cache, that cache MUST NOT use the entry after it becomes stale to respond to a subsequent request without first revalidating it with the origin server.当缓存收到的响应中存在 must-revalidate 指令时,该缓存在它变得陈旧后不得使用该条目来响应后续请求,而无需先与源服务器重新验证它。 (Ie, the cache MUST do an end-to-end revalidation every time, if , based solely on the origin server's Expires or max-age value, the cached response is stale .) (即,缓存必须每次都进行端到端的重新验证,如果仅基于源服务器的 Expires 或 max-age 值,则缓存的响应是陈旧的。)

Since you do not provide explicit expiration, caches are allowed to use heuristics to determine freshness .由于您不提供明确的到期时间, 因此允许缓存使用启发式方法来确定新鲜度

Since you do not provide Last-Modified caches do not need to warn the client that heuristics was used.由于您不提供Last-Modified缓存,因此不需要警告客户端使用了启发式方法。

If none of Expires, Cache-Control: max-age, or Cache-Control: s- maxage (see section 14.9.3) appears in the response, and the response does not include other restrictions on caching, the cache MAY compute a freshness lifetime using a heuristic .如果响应中没有出现 Expires、Cache-Control: max-age 或 Cache-Control: s-maxage(参见第 14.9.3 节),并且响应不包含其他缓存限制,则缓存可以计算新鲜度使用启发式的生命周期 The cache MUST attach Warning 113 to any response whose age is more than 24 hours if such warning has not already been added.如果尚未添加此类警告,则缓存必须将警告 113 附加到年龄超过 24 小时的任何响应。

The response age is calculated based on Date header since Age is not present.由于Age不存在,因此响应年龄是根据Date标头计算的

If the response is still fresh according to heuristic expiration, caches may use the stored response.如果根据启发式过期响应仍然是新鲜的,则缓存可以使用存储的响应。

One explanation is that HttpWebRequest uses heuristics and that there was a stored response with status code 200 that was still fresh.一种解释是HttpWebRequest使用启发式方法,并且有一个状态代码为 200 的存储响应仍然是新鲜的。

Answering my own question..回答我自己的问题..

According to http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4 I would say that a "Cache-Control: must-revalidate" without expiration states that the resource should be validated on every request.根据http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4我会说没有过期的“缓存控制:必须重新验证”表明资源应该在每个要求。

In this case it means a conditional GET should be done every time the resource is made.在这种情况下,这意味着每次创建资源时都应该执行有条件的 GET。 So in this case System.Net.Http.HttpClient is behaving correctly and the legacy (Http)WebRequest is doing invalid behavior.因此,在这种情况下 System.Net.Http.HttpClient 行为正确,而遗留 (Http)WebRequest 的行为无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM