为什么304响应没有更新本地缓存资源的新鲜度?

时间:2014-01-04 19:50:06

标签: http caching dotnet-httpclient

当我执行条件GET并使用Cache-Control max-age标头获得304响应时,我希望更新资源的新鲜度以及将来从本地缓存获取表示的请求,假设它是新鲜的。但是,我无法使用HttpClient来实现这一点。

这是我的复制,作为使用Nuget依赖项Microsoft.AspNet.WebApi.OwinSelfHostMicrosoft.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。

0 个答案:

没有答案