Http 为什么这个304响应不更新本地缓存资源的新鲜度?
当我执行一个条件GET并获得一个带有Cache-Control-max-age头的304响应时,我希望更新资源的新鲜度,并期望将来的请求从本地缓存获取表示(假设它是新鲜的)。但是,我无法使用HttpClient实现这一点 这是我的复制品,作为一个简单的.net 4.5控制台应用程序,使用Nuget dependenciesHttp 为什么这个304响应不更新本地缓存资源的新鲜度?,http,caching,dotnet-httpclient,Http,Caching,Dotnet Httpclient,当我执行一个条件GET并获得一个带有Cache-Control-max-age头的304响应时,我希望更新资源的新鲜度,并期望将来的请求从本地缓存获取表示(假设它是新鲜的)。但是,我无法使用HttpClient实现这一点 这是我的复制品,作为一个简单的.net 4.5控制台应用程序,使用Nuget dependenciesMicrosoft.AspNet.WebApi.OwinSelfHost和Microsoft.net.Http using System; using System.Net;
Microsoft.AspNet.WebApi.OwinSelfHost
和Microsoft.net.Http
using System;
using System.Net;
using System.Net.Cache;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Web.Http;
using Microsoft.Owin.Hosting;
using Owin;
namespace TestEtag
{
class Program
{
static void Main(string[] args)
{
// Run as administrator to allow web server to start.
// Clear browser cache to see initial 200 response when running multiple times
var host = String.Format("http://{0}:8080/", Environment.MachineName);
var server = WebApp.Start(host, app =>
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
});
Console.WriteLine("Started Web server");
var clientHandler = new WebRequestHandler();
clientHandler.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
var client = new HttpClient(clientHandler) { BaseAddress = new Uri(host) };
var response = client.GetAsync("/resource").Result; // Should return response
Console.WriteLine("returned response " + response.StatusCode);
var response2 = client.GetAsync("/resource").Result; // Should get from local cache (and does)
Console.WriteLine("returned response " + response2.StatusCode);
Console.WriteLine("Pause for resource to expire");
Thread.Sleep(7000);
var response3 = client.GetAsync("/resource").Result; // Should make conditional get and get 304 (and does)
Console.WriteLine("returned response " + response3.StatusCode);
var response4 = client.GetAsync("/resource").Result; // Should get from local cache (but doesn't)
Console.WriteLine("returned response " + response4.StatusCode);
Console.ReadLine();
server.Dispose();
}
}
[Route("resource")]
public class ResourceController : ApiController
{
public HttpResponseMessage Get()
{
var etag = new EntityTagHeaderValue("\"XYZPQR\"");
if (Request.Headers.IfNoneMatch != null)
{
if (Request.Headers.IfNoneMatch.Contains(etag))
{
var notModifiedresponse = new HttpResponseMessage(HttpStatusCode.NotModified);
notModifiedresponse.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = new TimeSpan(0, 0, 0, 5) };
notModifiedresponse.Headers.ETag = etag;
return notModifiedresponse;
}
}
var response = new HttpResponseMessage()
{
Content = new StringContent("This is cached content with an etag")
};
response.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = new TimeSpan(0, 0, 0, 5) };
response.Headers.ETag = etag;
return response;
}
}
}
我相信最后一个HTTP请求应该直接来自本地WinInet缓存,但是,您可以从fiddler中看到它正在发出网络请求并返回304
有人知道我做错了什么吗
更新 我尝试使用Expires而不是Max age,但我得到了相同的行为。该跟踪的一个子集显示以下内容:
System.Net.Cache Verbose: 0 : [15524] RequestCacheProtocol#2086040::GetRevalidateStatus(HttpWebRequest#10920143)
System.Net.Cache Information: 0 : [15524] StatusCode=304 NotModified System.Net.Cache Information: 0 : [15524] ValidateResponse(), result = Continue.
System.Net.Cache Information: 0 : [15524] After Response Cache Validation.
System.Net.Cache Information: 0 : [15524] Updating headers on 304 response.
System.Net.Cache Information: 0 : [15524] RevalidateCache(), result = ReturnCachedResponse.
System.Net.Cache Verbose: 0 : [15524] Exiting RequestCacheProtocol#2086040::GetRevalidateStatus() -> result = ReturnCachedResponse
System.Net.Cache Verbose: 0 : [15524] RequestCacheProtocol#2086040::GetUpdateStatus()
System.Net.Cache Information: 0 : [15524] Response Status = NotModified.
System.Net.Cache Information: 0 : [15524] Valid based on Status Code: 304.
System.Net.Cache Information: 0 : [15524] Response==304 or Request was HEAD, updating cache entry.
System.Net.Cache Information: 0 : [15524] Update Cached Headers.
如您所见,日志声明缓存项已更新
System.Net.Http Information: 0 : [15524] HttpClient#17533994 - Request for HttpRequestMessage#55917598 completed successfully. Returning response HttpResponseMessage#39055747: StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Date: Tue, 07 Jan 2014 18:12:18 GMT
ETag: "XYZPQR"
Server: Microsoft-HTTPAPI/2.0
Age: 0
Content-Length: 35
Content-Type: text/plain; charset=utf-8
Expires: Tue, 07 Jan 2014 18:12:23 GMT }
此响应的过期日期显示为18:12:23
最后一个请求显示正在找到缓存响应
System.Net.Cache Information: 0 : [10644] WinInetCache.Retrieve() -> Filename = C:\Users\darrel.TAVIS\AppData\Local\Microsoft\Windows\INetCache\IE\P6AEJQC4\resource[1].cache, Status = Success.
System.Net.Cache Verbose: 0 : [10644] Exiting WinInetCache.Retrieve()() Status = Success System.Net.Cache Information: 0 : [10644] ...Dumping Cache Context...
System.Net.Cache Information: 0 : [10644] IsPrivateEntry = True
System.Net.Cache Information: 0 : [10644] IsPartialEntry = False
System.Net.Cache Information: 0 : [10644] StreamSize = 35
System.Net.Cache Information: 0 : [10644] Expires = Tue, 07 Jan 2014 18:12:13 GMT
System.Net.Cache Information: 0 : [10644] LastAccessed = Tue, 07 Jan 2014 18:12:19 GMT
System.Net.Cache Information: 0 : [10644] LastModified =
System.Net.Cache Information: 0 : [10644] LastSynchronized = Tue, 07 Jan 2014 18:12:08 GMT
System.Net.Cache Information: 0 : [10644] MaxStale(sec) = 0
System.Net.Cache Information: 0 : [10644] HitCount = 4
System.Net.Cache Information: 0 : [10644] UsageCount = 2
System.Net.Cache Information: 0 : [10644] EntryMetadata:
System.Net.Cache Information: 0 : [10644] HTTP/1.1 200 OK System.Net.Cache Information: 0 : [10644] Content-Length: 35 System.Net.Cache Information: 0 : [10644] Content-Type: text/plain; charset=utf-8 System.Net.Cache Information: 0 : [10644] Date: Tue, 07 Jan 2014 18:12:08 GMT System.Net.Cache Information: 0 : [10644] Expires: Tue, 07 Jan 2014 18:12:13 GMT System.Net.Cache Information: 0 : [10644] ETag: "XYZPQR"
System.Net.Cache Information: 0 : [10644] Server: Microsoft-HTTPAPI/2.0 System.Net.Cache Information: 0 : [10644] --- System.Net.Cache Information: 0 : [10644] SystemMetadata:
System.Net.Cache Information: 0 : [10644] Entry Status Line = HTTP/1.1 200 OK.
System.Net.Cache Information: 0 : [10644] Cache Cache-Control = .
System.Net.Cache Information: 0 : [10644] [Now Time (UTC)] = Tue, 07 Jan 2014 18:12:19 GMT.
System.Net.Cache Information: 0 : [10644] [Age1] NowTime-Date Header = 11, Date Header: Tue, 07 Jan 2014 18:12:08 GMT.
System.Net.Cache Information: 0 : [10644] [MaxAge] Cache Expires - Date = 5, Expires: Tue, 07 Jan 2014 18:12:13 GMT.
System.Net.Cache Information: 0 : [10644] ValidateFreshness(), result = Stale.
System.Net.Cache Information: 0 : [10644] Cache Age = 11, Cache MaxAge = 5.
System.Net.Cache Information: 0 : [10644] Request Condition = If-None-Match:"XYZPQR".
System.Net.Cache Information: 0 : [10644] ValidateCache(), result = Continue.
但是,缓存的Expires条目在304响应中仍然显示为18:12:13,而不是18:12:23。结果是缓存的条目被视为过时,我们支付返回服务器的往返费用以获得另一个304。如果重新启动程序,您将看到4次请求和
304
响应。也许缓存会忽略资源,因为它的重复使用寿命很短?@CodeCaster这是因为表示被持久化到WinInet缓存中的磁盘。如果不清除浏览器缓存,第一个请求将是有条件的,从那时起,新鲜度将永远不会更新。这是我问题的核心。使用ETag的性能比不使用ETag的性能差。您是否尝试启用System.Net跟踪,以了解它是否揭示了响应未被缓存的原因@是的。我用日志中的结果更新了问题。