Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expires headers when testing in Chrome

Getting very confused about 'Expires' header here! Sometimes it works as expected - and some times not.

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 'filterContext' is coming from.

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");

This will sometimes give me headers like this :

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

Sometimes like this :

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

I am running everything through Fiddler and watching to see when things are re-requested and when they come from the browser cache.

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.

However in Chrome it sometimes will and sometimes won't come from cache! By coming from cache I mean no additional HTTP request.

For instance a link like this :

 http://ipv4.fiddler:62669/gallery/mainimage/2

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.

Is Chrome trying to do something 'clever' and just failing miserably - or do I need an additional header?

What I'm wondering is if it has anything to do with the fact that my Expires header date is never actually in the future. if I look at google's headers for their hosted jQuery file I see that the headers are as follows (with Expires here in 2010 - one year in the future).

Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 05:44:53 GMT
Expires: Thu, 18 Feb 2010 05:44:53 GMT

Shouldn't Expires actually be in the future??

According to the HTTP spec :

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.

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.

like image 422
Simon_Weaver Avatar asked Oct 15 '22 17:10

Simon_Weaver


1 Answers

I've pretty much concluded that it is Chrome doing something REALLY REALLY whacky with caching.

I simplified it to the lowest possible level - getting jQuery from Google's server.

I typed in :

http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js 

to Chrome, and Fiddler came up with the following 200 request :

Requests started at:    22:58:00:7756
Responses completed at: 22:58:03:5020
Total Sequence time:    00:00:02.7263880
DNS Lookup time:    531ms
TCP/IP Connect time:    63ms

RESPONSE CODES
--------------
HTTP/200:   1

The headers were as follows (note Expires is 1 year after today):

Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 06:58:01 GMT
Expires: Thu, 18 Feb 2010 06:58:01 GMT
Vary: Accept-Encoding

and then i waited a few seconds and hit enter - in the same tab. Fiddler came up with ANOTHER **200* request:

Requests started at:    22:58:09:2516
Responses completed at: 22:58:12:3999
Total Sequence time:    00:00:03.1482360

RESPONSE CODES
--------------
HTTP/200:   1

And the headers were :

Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 06:58:09 GMT
Expires: Thu, 18 Feb 2010 06:58:09 GMT
Vary: Accept-Encoding

Obviously this is NOT what I was expecting.

Yes - Accept-Encoding was the same for both requests.

Yes - A third request gave me a 304

This was on a new install of Chrome that I'd never done any development on - and on which I'd only just installed Fiddler for the first time.

I cant wait for someone to explain that to me. For now I'm giving up - I think my caching and expiration code is fine. In addition ASP.NET MVC appears to be forcing Expires to be the current time. This obviously isn't a factor in my google example.

I think Chrome is being too clever and this has to be a bug - I'm on version 1.0.154.48.

like image 121
Simon_Weaver Avatar answered Oct 18 '22 12:10

Simon_Weaver