Reputation: 992
I have a php script that generates *.png pictures but does not store them on the server. Those pictures will be shown to a same user repeatedly. I'm looking for a way to cache those pictures. I'm able to send the 304 status header, the browser also declares the webpage as cached at first refresh (as it is visible in the web-inspector) but the webpage is shown blank. After a second refresh even the web-inspector shows blank.
Can someone help me and tell where I messed up?
Notes:
Here are the main lines of the file:
session_start();
header("Content-type: image/jpeg");
//A little require_once() here on some functions stored in an other file.
$originalSource = getSource($_GET['src']);
if (isset($_COOKIE[sha1($originalSource)]) && $_COOKIE[sha1($originalSource)]) {
header("HTTP/1.1 304 Not Modified");
die;
} else {
setcookie (sha1($originalSource), true, time()+10);
$offset = 10;
$expire = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
header($expire);
header("Cache-Control: max-age=".$offset);
header("Last-Modified: Wed, 25 Feb 2015 12:00:00 GMT");
}
//The entire image generation process after this
Thanks for your help 💛
Upvotes: 1
Views: 1215
Reputation: 522016
Your server is the one deciding here whether it thinks the browser should still have the image cached or not. Obviously it is hardly the authority on that. There are any number of reasons why the browser may not have the image cached, e.g. if you open the inspector tools (which typically disables caching).
The browser has a mechanism for informing the server about its cache status: the HTTP headers If-None-Match
for ETags and If-Modified-Since
for time-based expiry. If any of these two headers is present in the request, that means the browser still has a copy of the resourced cached and would happily accept a 304
response instead of downloading the resource again.
If you set an ETag
header in your response, the browser will do another request using If-None-Match
(that essentially replaces your cookie mechanism, more reliably); if you just set an expiration date, the browser will check again with the server using the If-Modified-Since
header. That's what you should base your 304
reply on.
Example using ETags:
$hash = sha1($originalSource);
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT");
if (
isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $hash
) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header("Content-type: image/jpeg");
header("Cache-Control: max-age=$offset");
header("ETag: \"$hash\"");
// output image
Upvotes: 2