Firefox 1.0.x/Mozilla fails to adhere to HTTP/1.1 must-revalidate specifications

RESOLVED INVALID

Status

()

Core
Networking
--
major
RESOLVED INVALID
13 years ago
2 years ago

People

(Reporter: Chris, Unassigned)

Tracking

1.7 Branch
x86
Linux
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

13 years ago
User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050921 Red Hat/1.0.7-1.4.1 Firefox/1.0.7
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050921 Red Hat/1.0.7-1.4.1 Firefox/1.0.7

In our customer websites we have multi language support, but the URL remains the same. ie you would go to:

Goto: http//www.myhost.com/Home <- Shows page in dutch
..Click English (posts a language=en_US to the page)..
Goto: http//www.myhost.com/Home <- Shows page in english
.. Click 'Home' button that goes to /Home ..
http//www.myhost.com/Home <- Shows page in dutch (!!)

Since the first click is a post, the english version is properly displayed, however after that the page language to use is determined by a cookie .. 

So when clicking to that page again it uses the cached version of the (none-post) page, which is in dutch, even though the cookie is set to (and the server generates) an english page.

To try to tell mozilla/firefox that they should do a etag / if-modified-since check on the page (etag will be different for the different language), i added a  "Pragma: must-revalidate" header to the pages.

However when looking at firefox's activity using 'liveHTTPHeaders' (firefox plugin) and ethereal (to doublecheck), firefox doesn't do any requests to the server (to verify etag/if-modified-since), and the server never gets the chance to tell firefox that the page is different ...

The confusing thing is that looking at RFC 2616 the must-revalidate header does tell the browser to check the page (in RFC terminology "the cache MUST do an end-to-end revalidation every time"), but it doesn't!

Currently my only option seems to be to add a no-cache, no-store and remove all 'modified' headers... which just horribly abuses the caching system and the "way its supposed to work". (ie makes the website slow for our customers), that can never be the intend can it?


From the RFC which can be found at: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html


must-revalidate
    Because a cache MAY be configured to ignore a server's specified expiration time, and because a client request MAY include a max- stale directive (which has a similar effect), the protocol also includes a mechanism for the origin server to require revalidation of a cache entry on any subsequent use. When the must-revalidate directive is present in a response received by a cache, that cache MUST NOT use the entry after it becomes stale to respond to a 
    subsequent request without first revalidating it with the origin server. (I.e., the cache MUST do an end-to-end revalidation every time, if, based solely on the origin server's Expires or max-age value, the cached response is stale.) 
    The must-revalidate directive is necessary to support reliable operation for certain protocol features. In all circumstances an HTTP/1.1 cache MUST obey the must-revalidate directive; in particular, if the cache cannot reach the origin server for any reason, it MUST generate a 504 (Gateway Timeout) response. 
    Servers SHOULD send the must-revalidate directive if and only if failure to revalidate a request on the entity could result in incorrect operation, such as a silently unexecuted financial transaction. Recipients MUST NOT take any automated action that violates this directive, and MUST NOT automatically provide an unvalidated copy of the entity if revalidation fails. 
    Although this is not recommended, user agents operating under severe connectivity constraints MAY violate this directive but, if so, MUST explicitly warn the user that an unvalidated response has been provided. The warning MUST be provided on each unvalidated access, and SHOULD require explicit user confirmation.




Reproducible: Always

Steps to Reproduce:
Create a page in (php/perl/etc) that outputs a different content based on a cookie (under the same URL, without post/get's), and uses a valid proper etag (which is an md5 or sha1 of the content), which is different between page versions.Click refresh (in your toolbar or ctrl-r), and the proper page is displayed (since the e-tag is different and the page content is transfered).

However click a link to the page, and it shows the incorrect version without checking with the server if If-Modified-Since or the If-None-Match returns a '304' (Not modified) header.
> To try to tell mozilla/firefox that they should do a etag / if-modified-since
> check on the page (etag will be different for the different language), i added
> a  "Pragma: must-revalidate" header to the pages.

> From the RFC which can be found at:
> http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

There is no "Pragma: must-revalidate" in that specification. There is a "Cache-Control: must-revalidate", however.
Status: UNCONFIRMED → RESOLVED
Last Resolved: 13 years ago
Resolution: --- → INVALID
(Reporter)

Comment 2

13 years ago
Ok you were absolutely right and it was my late friday desire for weekend that led me to my incorrect assumtion of the pragma header :-)

However it being monday again i went to impliment the "Cache-Control: must-revalidate" header, and the problem remains the same as described in the original bug report.

To verify my headers come thru ok i ran wget -S:
  HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Date: Mon, 31 Oct 2005 08:22:03 GMT
  Server: Apache/2.0.52 (Red Hat)
  X-Powered-By: PHP/5.0.5
  Set-Cookie: ZDEDebuggerPresent=php,phtml,php3; path=/
  Content-Language: nl
  Last-Modified: Tue, 19 Jul 2005 07:50:54
  Connection: Keep-Alive, Keep-Alive
  Keep-Alive: timeout=15, max=100
  Cache-Control: must-revalidate
  Accept-Ranges: bytes
  Content-Length: 6278
  ETag: ice-4fd435b7ad6992a9a64e23069bca3775c488de29
  Content-Type: text/html; charset=utf-8

So that seems to work ok .. both e-tag is valid, so is last modified, and so is the cache-control.

So when i change the language (thru setting a cookie) and click a link to that page, i would expect firefox to revalidate with a "If-Modified-Since" and/or "If-None-Match" request, and check to see if it got a full page (200 OK) or a Not modified (HTTP/1.1 304 Not Modified).

However this doesn't happen, it does not revalidate the cached version .. And it shows the page which it has cached, which is invalid (ie in the wrong language!). 

The easy way out ofcourse would be to set no-cache, no-store, expires in the past and all those tricks, but that wouldn't be nice for our end users, nor in the spirit of the internet :-)
Status: RESOLVED → UNCONFIRMED
Resolution: INVALID → ---

Updated

13 years ago
Assignee: nobody → darin
Component: General → Networking
Product: Firefox → Core
QA Contact: general → benc
Version: unspecified → 1.7 Branch
(Reporter)

Comment 3

13 years ago
Ps by adding an "Expires:" set to one second in the future header, the browser DOES revalidate the content, however just the cache-control must-revalidate doesn't cause this, neither does adding a max-age: 1 or 0 to the cache-control..
hm? RFC 2616 says:
> (I.e., the cache MUST do an end-to-end revalidation every
>       time, if, based solely on the origin server's Expires or max-age
>       value, the cached response is stale.)

(which you misquoted in comment 0). That explicitly says that revalidation is only necessary if the page is stale per the Expires (or max-age) value. Where's the bug?
(Reporter)

Comment 5

13 years ago
In reply to comment #4
> only necessary if the page is stale per the Expires (or max-age) value.
> Where's the bug?

When you don't send an expires or max-age, the browser does not revalidate it with the origin server, but assumes it doesn't expire ... ever ..

However when i was reading RFC2616 and read the description of the must-revalidate cache control, it read to me that "it must validate the validity of the cache, this CAN be thru checking the max age or expiration", ie this implies if no expiration, and no max age are set, and those means do not provide propper validation (since there is none) that the browser would ask the origin server if the cached information it has is valid. 

However if the assumption is made that a page without expires and/or max-age headers is never stale, then there's no bug i guess :-)

However the text in the RFC "MUST NOT automatically provide an unvalidated copy of the entity if revalidation fails" made me think that if no expiration and max-age is set, this would mean the browser "MUST" validate the cache with the server (resulting in either an 304 or 200 responce)

Again i assumed it would revalidate based on the RFC, but i also know what the say about assumptions; If the RFC had said must-revalidate was ONLY valid for cached content with an expiration or max-age, i never would have assumed it would have worked with just an must-revalidate, but reading the text i thought it was optional. But i could be wrong :-)
(In reply to comment #5)
> When you don't send an expires or max-age, the browser does not revalidate it
> with the origin server, but assumes it doesn't expire ... ever ..

It is supposed to calculate an expiry value, does that not work? What does about:cache show?

> However when i was reading RFC2616 and read the description of the
> must-revalidate cache control, it read to me that "it must validate the
> validity of the cache, this CAN be thru checking the max age or expiration", ie
> this implies if no expiration, and no max age are set, and those means do not
> provide propper validation (since there is none) that the browser would ask the
> origin server if the cached information it has is valid. 

If the server doesn't send an expires header, one is calculated... (based on Last-Modified and Date)

Comment 7

13 years ago
I encountered the bug in the same situation: different language version of an image are at the same URL. A cookie may be set by the server that overrides the Accept-Languages header.

Things worked perfectly as long as I did not provide a Last-Modified header, and no header with caching information at all.

Know I've started to return a "Last-Modified" header which returns the "date and time at which the origin server believes the variant was last modified" (rfc2616). Firefox now seems to assume that revalidating isn't necessary as the representation didn't change for the last two years, however it should imho consider, that change in "Cookie" header may cause another representation of the resource to be delivered. 

Disabling cache is an ugly work-around, as the client can safely assume, that the server would deliver the same representation for an identical request.
>  Firefox now seems to assume that revalidating isn't necessary as the
> representation didn't change for the last two years, however it should imho
> consider, that change in "Cookie" header may cause another representation of
> the resource to be delivered. 

don't you need to send a Vary: Cookie header in that case?

Updated

12 years ago
Assignee: darin.moz → nobody
QA Contact: benc → networking
Status: UNCONFIRMED → RESOLVED
Last Resolved: 13 years ago2 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.