buunguyen / combres

ASP.NET and MVC performance optimization library ⛺
Other
123 stars 37 forks source link

Refine cache control configuration #15

Closed mikaelnet closed 10 years ago

mikaelnet commented 11 years ago

Hi,

The RequestProcessor.SendOutputToClient sets both MaxAge and Expires headers. This is valid and MaxAge should be used in favor of Expires by clients. But this seems to be a bit buggy in some implementations. Amazon CloudFront in particular, has problems with this (http://www.cdnplanet.com/blog/cloudfront-cachability-date-header/).

I suggest removing the Expires heading, or make it configurable as in IIS . There are very few clients today anyway that don’t support MaxAge and do we really care about caching for those clients? Let’s release those extra bytes in the header for all other users instead. (Of course I'd prefer if Amazon could fix the error in their end, but this has been a known bug for years.)

/ Mikael

buunguyen commented 11 years ago

What is the problem with having both MaxAge and Expires set (assume they're set with correct values)?

mikaelnet commented 11 years ago

The main problem is that the Expires header does not get updated in a CloudFront distribution. Let's say we expires a file in a week, the first request from the CDN will be ok. It will have an expires header one week ahead and the CDN will automatically decrease the max-age of the file as we go close to the expiry date.

Assume we don't do any modifications on the server. When we pass the expiry date, CloudFront will refetch the file from the web server. Combres will, correctly, return a "304 not modified" since the etag is the same. CloudFront now resets the max-age counter to be valid for another week. But, the Expires-header remains unchanged. CloudFront keeps the cached versions of the headers as well as the content. So, now we have a valid max-age header but an Expires header that's in the passed.

buunguyen commented 11 years ago

That makes sense. Thanks for clarifying. I will remove the expires header.

buunguyen commented 10 years ago

Now that I look at it more closely, from the HTTP 1.1 spec, it says that:

"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." (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)

I suppose even if CloudFront doesn't set the correct Expires header, it shouldn't affect HTTP 1.1 agents. As for HTTP 1.0 ones, they wouldn't benefit from caching anyway if Expires header isn't set. At least having it set help those that don't use CloudFront.

Thought?