New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 898981 link

Starred by 4 users

Issue metadata

Status: Unconfirmed
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug



Sign in to add a comment

Cache-Control Header not fully honored (Cache-Control: public, max-age=604800, must-revalidate, s-maxage=3600, stale-while-revalidate=3600, stale-if-error=14400)

Reported by mroche...@gmail.com, Oct 25

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36

Steps to reproduce the problem:
###### TEST PAGE ##### 
https://static1.st8fm.com/en_US/applications/b2c/cachetest/index.html

##################
1. Load the the web page with the the defined resources.
2. Without opening the developer tools, update a script.js file and republish to the production / CDN
3. Reload the pages without purging the cache and the new content should be invalidated, and pull the new script.js file down based on the  `If-Modified-Since` rule set.

If the developer tools are opened after the update is made the page pulls the new content from the production server / CDN.

When a validation request is made, the server can either ignore the validation request and response with a normal 200 OK, or it can return 304 Not Modified (with an empty body) to instruct the browser to use its cached copy. The latter response can also include headers that update the expiration time of the cached document

The CDN does response with the 304 with all other browsers tested with.

##################
In order to reproduce in our environment we would need to publish update files for your team.  

##################
GENERAL
Request URL: https://static1.st8fm.com/en_US/applications/b2c/cachetest/js/script.js
Request Method: GET
Status Code: 200 OK (from memory cache)
Remote Address: 10.182.117.23:443
Referrer Policy: no-referrer-when-downgrade

RESPONSE HEADER
HTTP/1.1 200 OK 
Date: Thu, 25 Oct 2018 17:11:28 GMT
Last-Modified: Thu, 18 Oct 2018 14:31:01 GMT
Accept-Ranges: bytes
Content-Length: 168
Cache-Control: public, max-age=604800, must-revalidate, s-maxage=3600, stale-while-revalidate=3600, stale-if-error=14400
Expires: Thu, 25 Oct 2018 21:11:28 GMT
Keep-Alive: timeout=5, max=97
Connection: Keep-Alive
Content-Type: application/javascript

REQUEST HEADER:
GET /en_US/applications/b2c/cachetest/js/script.js HTTP/1.1
Host: static1.st8fm.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
DNT: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: */*
Referer: https://static1.st8fm.com/en_US/applications/b2c/cachetest/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,es;q=0.8

What is the expected behavior?
The content to be cached locally for one month but the browser should re-validate before serving from the local cache; the client should issue an `If-Modified-Since` request header to validate the content.

Full details: 
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching

Google Documentation: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#defining_optimal_cache-control_policy

What went wrong?
The re-validation trigger does not seem to fire, the content is loaded from 

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 67.0.3396.99  Channel: stable
OS Version: 10.0
Flash Version: 

As a company we are looking at solutions to cache our content longer.  Changing purely static content to a year cache.  For content in our agile flow we are looking at two different solutions.  Finger printing for application specific file that a team can control, and the use of Cache-Control for global files that change often.  Our current infrastructure design does not allow for these specific file to be finger-printed/hashed.
 
static1.st8fm.com.har
1.0 MB Download
Opened under the wrong account:  Owner should be michael.roche.hurg@statefarm.com
Components: Internals>Network>Cache
Cc: michael....@statefarm.com morlovich@chromium.org
So I am not sure I understand your report correctly; do you expect a conditional request to be sent every single time?

My reading of RFC 7234 doesn't seem to require this behavior. For must-revalidate, it says, in https://tools.ietf.org/html/rfc7234#section-5.2.2.1 

   The "must-revalidate" response directive indicates that once it has
   become stale, a cache MUST NOT use the response to satisfy subsequent
   requests without successful validation on the origin server.

Notice that it's conditionalized on "once it has become stale".

Meanwhile:
5.2.2.8.  max-age

   Argument syntax:

      delta-seconds (see Section 1.2.1)

   The "max-age" response directive indicates that the response is to be
   considered stale after its age is greater than the specified number
   of seconds.

So if I understand correctly, must-revalidate only kicks in when max-age=604800  (or for intermediary proxy caches,  s-maxage=3600) has expired.

Labels: Needs-Milestone
So the must-revalidate directive is always unnecessary (at least in the browser side)? Because "revalidating after stale" is the default HTTP cache behaviour.

Also see the new stale-while-revalidate directive(still in the experiment stage) https://bugs.chromium.org/p/chromium/issues/detail?id=348877#c81
That's a good point, I can't think of when it's useful off the top of my head. 
We seem to disable heuristic implicit caching (i.e. that of resources without max-age or expires) on must-revalidate, but I am not sure that's actually required by the spec:

https://tools.ietf.org/html/rfc7234#section-4.2.4

"   A "stale" response is one that either has explicit expiry information
   or is allowed to have heuristic expiry calculated, but is not fresh
   according to the calculations in Section 4.2.
"

The code itself quotes the older RFC 2616:
https://cs.chromium.org/chromium/src/net/http/http_response_headers.cc?rcl=067b7dcc6f5f64816d67a296c8493339bce51134&l=1053

... which does seem to be require max-age/expires. I wonder why it changed...

(must-revalidate also disables stale-while-revalidate for us)

The purpose for must-revalidate is to indicate if we're unable to reach the server for revalidation, we shouldn't fall back to the cached version, I think?

Normally, for back/forward operations, at least, Chrome will prefer the cached version, stale or not, without checking with the server.  We presumably shouldn't in the must-revalidate case, I assume?  Could also imagine a browser that would use stale resources while offline, by default, which also shouldn't be done in the must-revalidate case.
>> We seem to disable heuristic implicit caching

Indeed https://cs.chromium.org/chromium/src/net/http/http_response_headers.cc?type=cs&q=must-revalidate+-file:test+lang:%5Ec%5C%2B%5C%2B$&sq=package:chromium&g=0&l=1065 I tested on Firefox and didn't find the same behavior.


My understanding of the definition for "must-revalidate" is similar to 'revalidation triggered when the user presses the reload button.'  

[https://tools.ietf.org/html/rfc7234#section-4.3.2]
    If a cache receives a request that can be satisfied by reusing one of
   its stored 200 (OK) or 206 (Partial Content) responses, the cache
   SHOULD evaluate any applicable conditional header field preconditions
   received in that request with respect to the corresponding validators
   contained within the selected response.  A cache MUST NOT evaluate
   conditional header fields that are only applicable to an origin
   server, found in a request with semantics that cannot be satisfied
   with a cached response, or applied to a target resource for which it
   has no stored responses; such preconditions are likely intended for
   some other (inbound) server.


Our company goal is to support Googles caching direction by having a very long cache (one week, one month or greater, in some cases a year) and then have the browser validate that the resource is still valid.  With HTTP/2.0 the additional transactions are small enough to not block the loading of the page.  We estimate the packet size to be about 80 bytes for the header request and response.  Thus a 304 response would trigger the loading of the cached content, saving considerable bandwidth.  

REF: HTTP/2; performance benefits; Push resources [https://developers.google.com/web/fundamentals/performance/http2]




Labels: Triaged-ET
morlovich@ A gentle ping..

Request you to check and provide an update on this issue.

Thanks..
Would it be possible to know if their will be a change added to the backlog to fix or update the process flow for cache re-validation?  
Is it possible to have a response to this issue, or provide some finial feedback.  We are trying to determine if we can move forward with design changes to use the `Cache-Control: public, max-age=604800, must-revalidate` portion.   See Comment 9 (#c9)
Labels: TE-NeedsTriageHelp
As this issue is related to Network>Cache and is out of scope of triaging at TE end, adding 'TE-NeedsTriageHelp' label and requesting the appropriate team to look into the issue and help in further triaging.

Thanks..
Cc: jasonjmi...@chromium.org
> The CDN does response with the 304 with all other browsers tested with.

@reporter see https://bugs.chromium.org/p/chromium/issues/detail?id=654378,Chrome stopped revalidating subresources while page reloading two years ago,Safari followed in 2017 https://bugs.webkit.org/show_bug.cgi?id=169756,but Firefox chose Cache-Control: immutable https://bugzilla.mozilla.org/show_bug.cgi?id=1267474.

Should the must-revalidate directive prevent NonValidatingReload? 	toyoshim@

Sign in to add a comment