I am serving images through php and having some problems setting it up to respond with 304 headers to save on load time.
Most of the code below I found on php.net. I
I believe it should be
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) >= $file_time)) {
Checking if the modified time is greater than or equal rather than just equal. Although I do understand the two values should be the same.
mandor at mandor dot net posted a solution at the PHP.net documentation for the header function which worked for me:
<?php
// Test image.
$fn = '/test/foo.png';
// Getting headers sent by the client.
$headers = apache_request_headers();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
header('Content-Length: '.filesize($fn));
header('Content-Type: image/png');
print file_get_contents($fn);
}
?>
Check if sessions are being used on that page, If so, try this:
session_cache_limiter(false);
If the above worked, here's the explanation:
Php's session mechanism sends some automatic cache-related headers in order to improve the session cookie privacy, avoiding it to be cached by intermediate proxyes:
http://php.net/manual/en/function.session-cache-limiter.php
These automatic headers cause the browser not to ever send the If-Modified-Since header, as they instruct it to not to perform any caching at all.
After searching for a while, I've found the answer. The browser didn't cached anything (and didn't send the If-Modified-Since
) until I sent the following header:
Cache-Control: private;
After doing this all worked fine.
I had to use Keith's solution with combination of azkotoki's and Zsolti's posts above to make everything work as required.
so, final example would be:
<?php
// Test image.
$fn = '/test/foo.png';
session_cache_limiter(false);
header('Cache-Control: private');
// Getting headers sent by the client.
$headers = apache_request_headers();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
header('Content-Length: '.filesize($fn));
header('Content-Type: image/png');
print file_get_contents($fn);
}
?>