title: Expires headers when testing in Chrome
body: <p>Getting very confused about 'Expires' header here!
  Sometimes it works as expected - and some times not.</p>
  
  <p>I am using the following code to set my expiration headers. Note this is being done with ASP.NET in an MVC custom attribute - thats not really relevant here - but explains where <code>'filterContext'</code> is coming from.</p>
  
  <pre><code>HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
  TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
  
  // my own custom header so we know what time it was
  filterContext.HttpContext.Response.AddHeader("CurrentTime", DateTime.Now.ToString());
  
  cache.SetCacheability(HttpCacheability.Public);
  cache.SetExpires(DateTime.Now.Add(cacheDuration));
  cache.SetMaxAge(cacheDuration);
  cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
  </code></pre>
  
  <p>This will sometimes give me headers like this :</p>
  
  <pre><code>Cache-Control: public, must-revalidate, proxy-revalidate, max-age=413
  Date: Wed, 18 Feb 2009 05:24:19 GMT
  Expires: Wed, 18 Feb 2009 05:21:12 GMT
  CurrentTime: 2/17/2009 9:21:12 PM
  </code></pre>
  
  <p>Sometimes like this :</p>
  
  <pre><code>Cache-Control: public, must-revalidate, proxy-revalidate, max-age=600
  Date: Wed, 18 Feb 2009 05:27:55 GMT
  Expires: Wed, 18 Feb 2009 05:27:55 GMT
  CurrentTime: 2/17/2009 9:27:55 PM
  </code></pre>
  
  <p>I am running everything through Fiddler and watching to see when things are re-requested and when they come from the browser cache.</p>
  
  <p>Now the weird thing is in IE the caching always works as expected. The link to my ASP.NET MVC action method appears in Fiddler and then when I click on that same link again it is coming from cache. </p>
  
  <p>However in Chrome it sometimes will and sometimes won't come from cache! By coming from cache I mean no additional HTTP request. </p>
  
  <p>For instance a link like this :</p>
  
  <pre><code> http://ipv4.fiddler:62669/gallery/mainimage/2
  </code></pre>
  
  <p>will come from cache in IE, but come back with a 200 in chrome. Then sometimes in Chrome it DOES come from the cache. I've tried emptying the browser cache and trying again - same result each time.</p>
  
  <p>Is Chrome trying to do something 'clever' and just failing miserably - or do I need an additional header?</p>
  
  <p>What I'm wondering is if it has anything to do with the fact that my <code>Expires</code> header date is never actually in the future. if I look at google's headers for their <a href="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" rel="nofollow noreferrer">hosted jQuery file</a> I see that the headers are as follows (with Expires here in 2010 - one year in the future).</p>
  
  <pre><code>Cache-Control: public, max-age=31536000
  Date: Wed, 18 Feb 2009 05:44:53 GMT
  Expires: Thu, 18 Feb 2010 05:44:53 GMT
  </code></pre>
  
  <p>Shouldn't Expires actually be in the future??</p>
  
  <p>According to the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html" rel="nofollow noreferrer">HTTP spec</a> :</p>
  
  <blockquote>
    <p>If a response includes both an Expires
    header and a max-age directive, the
    max-age directive overrides the
    Expires header, even if the Expires
    header is more restrictive. This rule
    allows an origin server to provide,
    for a given response, a longer
    expiration time to an HTTP/1.1 (or
    later) cache than to an HTTP/1.0
    cache. This might be useful if certain
    HTTP/1.0 caches improperly calculate
    ages or expiration times, perhaps due
    to desynchronized clocks.</p>
  </blockquote>
  
  <p>Therefore it seems that Chrome should respect the max-age directive even if 'Expires' is the same as the current time but it doesn't seem to be doing that.</p>