Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Http 为什么这个304响应不更新本地缓存资源的新鲜度?_Http_Caching_Dotnet Httpclient - Fatal编程技术网

Http 为什么这个304响应不更新本地缓存资源的新鲜度?

Http 为什么这个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;

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

这是我的复制品,作为一个简单的.net 4.5控制台应用程序,使用Nuget dependencies
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跟踪,以了解它是否揭示了响应未被缓存的原因@是的。我用日志中的结果更新了问题。