当我执行条件GET并使用Cache-Control max-age标头获得304响应时,我希望更新资源的新鲜度以及将来从本地缓存获取表示的请求,假设它是新鲜的。但是,我无法使用HttpClient来实现这一点。
这是我的复制,作为使用Nuget依赖项Microsoft.AspNet.WebApi.OwinSelfHost
和Microsoft.Net.Http
的简单.net 4.5控制台应用程序。
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。