Hi,
I'm writing a very simple module to allow private files caching.
- I have been searching a solution for a long time before posting here.
- I'm talking about browser cache.
- I work on my dedicated server with root access to apache/drupal settings.
- I want to cache images using different styles of and original file.
- And I have no problem with caching css/js files or images using public files system.
As you can read here the image_file_download function doesn't set Expires, Cache-Control and ETag headers for images.
// By not explicitly setting them here, this uses normal Drupal
// Expires, Cache-Control and ETag headers to prevent proxy or
// browser caching of private images.So i use a hook_file_download in this function to define them :
function privatefilescache_file_download($uri){
$year = 86400 * 365;
// Getting file info
$info = image_get_info($uri);
// For images files
if(isset($info['mime_type']) && strpos($info['mime_type'], 'image/') === 0){
$header = array(
'Cache-Control' => 'max-age='.$year.', private',
'Expires' => gmdate('D, d M Y H:i:s', time() + $year) .' GMT',
'ETag' => strtr(md5($info['file_size']), 0, 10)
);
drupal_set_message('<pre>'. print_r($header, TRUE) .'</pre>');
return $header;
}
}In my HTTP Header, i can see that Cache-Control, Expires and ETag are correctly set.
Request and Response parameters are equal but Last-Modified parameter is automatically set to the current date, and I have a 200 instead of 304 status code.
Even if i set Last-Modified to "Mon, 13 Aug 2012 14:35:00 GMT" for example, I still have a 200 status code.
The request :
Cache-Control:max-age=0
If-Modified-Since:Mon, 13 Aug 2012 14:35:00 GMT
If-None-Match:bec86aeee7d11a957751af645155a115The response :
Cache-Control:max-age=31536000, private
Date:Sun, 18 Nov 2012 18:11:07 GMT
ETag:bec86aeee7d11a957751af645155a115
Expires:Mon, 18 Nov 2013 18:11:07 GMT
Last-Modified:Mon, 13 Aug 2012 14:35:00 GMTI tried with 'public' instead of 'private' in Cache-Control. Still doesn't work.
Can it be an error in Apache configuration ?
How can I fix my problem?
I'm working on a private image bank, you understand why I have to deal with cache and private files system..
Comments
A suggestion
Hello,
I am not an expert on HTTP 304 messages :) However, I did a quick bit of research.
Here's a link to the W3 web site:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Here is what is says about 304 messages:
Note the "no body", my emphasis. In your code, aren't you explicitly sending a body with the following statement:
drupal_set_message('<pre>'. print_r($header, TRUE) .'</pre>');? Check the doc on drupal_set_message here:http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drupal_set_message/7. Note the source code contains
// Mark this page as being uncacheable.drupal_page_is_cacheable(FALSE);
Good Luck :)
Thinking is the best way to travel.
Doesn't work
Thank you for your message but it doesn't fix the problem.
Glad to have helped
Hello,
Glad to have helped.
Again, I'm not an expert on generating an HTTP 304. However, if the the W3 doc I referenced is current, then you need to explicitly instruct Drupal to finish (write, flush, close) as soon as the headers are written. Not content should be added to the response after the headers.
In addition, you need to make sure the client (web browser) is performing a "conditional get".
My prior point was, issuing the drupal_set_message() is one factor in the failure. Yes, you should remove it, however you have more to do. Again, I'm not an expert, so I'll leave this other folks to help you further.
Good Luck :)
Thinking is the best way to travel.
Hi, I had the same problem...
Hi,
I had the same problem... No Caching is no option. So here is how it works for me, I adjusted your example, all managed files are cached:
<?php
function privatefilescache_file_download($uri){
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$ifs = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
$file = db_select('file_managed', 'fm')
->fields('fm')
->condition("uri", $uri)
->execute()
->fetchAssoc();
if(!empty($file)) {
$modified = $file['timestamp'];
if($modified < $ifs) {
header('HTTP/1.1 304 Not Modified');
exit();
}
}
}
$year = 86400 * 365;
$header = array(
'Cache-Control' => 'max-age='.$year,
'Expires' => gmdate('D, d M Y H:i:s', time() + $year) .' GMT',
'ETag' => strtr(md5($uri), 0, 10)
);
return $header;
}
?>
krisdigital
http://krisdigital.com