I’ve a really weird problem with the following simple php page saved at the root of my webserver as test.php:
<?
if( $_GET['img'] ) {
header('HTTP/1.0 304 Not Modified');
die();
} else {
header("Cache-Control: no-store, no-cache, must-revalidate");
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<body>
<img src="/test.php?img=1">
<a href="/not_existent_page.php">Dead link</a>
</body>
</html>
So when the page gets loaded, my server responds with the following headers:
Status Code 200
Cache-Control no-store, no-cache, must-revalidate
Content-Type text/html; charset=utf-8
Date Wed, 18 Jul 2012 12:00:43 GMT
Server Apache/2.2.22 (Ubuntu)
Strict-Transport-Security max-age=172800, includeSubDomains
Vary Accept-Encoding
x-frame-options sameorigin
x-powered-by PHP/5.4.4-1~precise+1
x-ua-compatible IE=edge
The interesting part are the cache headers: It says, do not cache!
The request for the picture after loading the page has the following response headers:
Status Code 304
Date Wed, 18 Jul 2012 12:02:20 GMT
Server Apache/2.2.22 (Ubuntu)
It does not say anything about caching (but that doesn’t matter anyway, I tested it).
With firefox and chrome the site behaves like it should: Each time I reload the page it gets reloaded as it should. If I click on the link, I get a 404 apache error.
With safari, the following happens:
If I open the page first, I see it.
When I reload the page within a short time (see below what “short time” means) it always gives me a blank site, when I click and the dead link it sometimes gives me a blank site, but I see the following headers in the web developer console of safari:
Status Code 304
Connection:Keep-Alive
Date:Wed, 18 Jul 2012 12:07:41 GMT
Keep-Alive:timeout=15, max=99
Server:Apache/2.2.22 (Ubuntu)
Vary:Accept-Encoding
The page stays blank! But: In my apache server logs, it says it returned all good with status code 200 on page reload:
// first page load
[18/Jul/2012:14:10:12 +0200] "GET /test.php HTTP/1.1" 200 979 "url/test.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2"
// request of picture with answer 304
[18/Jul/2012:14:10:12 +0200] "GET /test.php?img=1 HTTP/1.1" 304 266 "url/test.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2"
// reload within 10 seconds
[18/Jul/2012:14:10:19 +0200] "GET /test.php HTTP/1.1" 200 777 "url/test.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2"
(and a 404 when clicking the dead link.)
And now comes the interesting part: If I wait approx. 10+ seconds after loading the page, Safari behaves as expected: It simply loads the page again on reload without a 304 header (or displays a 404 on the dead link).
I have no problem with firefox and chrome at all.
So my question: Is safari mixing up the headers of the page, but only when loading the page again / clicking on a link within 10 seconds? How can I prevent this? Is this a bug in safari?
Btw: If I change the header to something else, Safari caches that header. So if I change test.php like this:
...
if( $_GET['img'] ) {
header('HTTP/1.0 204 No Content');
die();
} else {
....
The page reload now simply aborts without doing anything, but headers I see in safari console are 204 No Content.
One last thing: Reloading the page within 10 seconds triggers the error constantly, while sometimes clicking on the link works in safari, sometimes not.
/test.php will always set
header("Cache-Control: no-store, no-cache, must-revalidate");There is nothing interesting about the headers sayingdo not cachebecause you’re explicitly setting those headers./test.php?img=whatever will NEVER set the Cache-Control headers as above and will always return blank 304 Not Modified. You’re exiting right after the header() call. Technically it is not an image to apache. It’s mime type will be text/html so it will carry your expires/caching as html and php (in your .conf and/or htaccess). Unless you do
header('Content-Type: image/jpeg', true);or similar.It’s also good to use the second parameter of header() in order to replace previous ones in some circumstances.
Try this instead. let me know if you get the same result