frox
asked on
cache friendliness and HTTP_IF_MODIFIED_SINCE
I have a PHP script that displays images. For a number of reasons I wanted the images not to be readily available through http, so I did a simple script to serve them.
This is TOTALY bad to cache, images get reloaded at every visit.
btw, these images never change, so once they are read they are there!
The problem is that
echo $_SERVER['HTTP_IF_MODIFIED _SINCE']';
returns nothing.
is it a problem of the apache configuration??
am I just dumb?
BTW, the images never change, so it would be even simpler than usual!
what should I do to save bandwidth?
This is TOTALY bad to cache, images get reloaded at every visit.
btw, these images never change, so once they are read they are there!
The problem is that
echo $_SERVER['HTTP_IF_MODIFIED
returns nothing.
is it a problem of the apache configuration??
am I just dumb?
BTW, the images never change, so it would be even simpler than usual!
what should I do to save bandwidth?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
This isn't quite what you asked for, but it might be what you need.
Apache's mod_rewrite allows you to make a PHP script look like an image to a browser.
Put this in your .htaccess file:
RewriteEngine on
RewriteRule ^(.*).jpg script_that_returns_image. php?image= $1 [NE]
If your are getting the image now through
/script_that_returns_image .php?image =smile
the code provided would allow you to call the image by the following URL:
/smile.jpg
That way, the browser can't tell the difference, and you can still control the output through PHP.
Apache's mod_rewrite allows you to make a PHP script look like an image to a browser.
Put this in your .htaccess file:
RewriteEngine on
RewriteRule ^(.*).jpg script_that_returns_image.
If your are getting the image now through
/script_that_returns_image
the code provided would allow you to call the image by the following URL:
/smile.jpg
That way, the browser can't tell the difference, and you can still control the output through PHP.
ASKER
For Zyloch:
I tried this
<?php
header('Cache-Control: only-if-cached');
echo time();
?>
But anytime I open the page I see the seconds changed.
I tried this
<?php
header('Cache-Control: only-if-cached');
echo time();
?>
But anytime I open the page I see the seconds changed.
only-if-cached tells a proxy to send its cached copy if it has it. You should try, like snoyes_jw has said, to use session_cache_limiter("pub lic") which allows the user's machine to cache.
ASKER
For snoyes_jw:
Also
<?php
session_cache_limiter("pub lic");
echo time();
?>
still shows the seconds that change.
Also
<?php
session_cache_limiter("pub
echo time();
?>
still shows the seconds that change.
Overall, it depends on whether the user ends up caching the images or not. The headers sent are only to allow it to. You could, of course, find a free webhost online that has unlimited bandwidth and allows hotlinking, but that's about all I can think of.
ASKER
I am sorry, I still don't get it.
What I would want to do is that if the user refreshes (even with F5) the script of the page gets refreshed as usual, but the scripts of the images do NOT get reloaded, i.e. they behave as normal images.
(will be away for 20 mins)
What I would want to do is that if the user refreshes (even with F5) the script of the page gets refreshed as usual, but the scripts of the images do NOT get reloaded, i.e. they behave as normal images.
(will be away for 20 mins)
I assume that the point of this question is to avoid people linking to your images from other sites. It might be simpler to just serve the images as normal, and use .htaccess to prevent hotlinks.
http://altlab.com/htaccess_tutorial.html
http://altlab.com/htaccess_tutorial.html
ASKER
to snoyes_jw:
> I assume that the point of this question is to avoid people
> linking to your images from other sites
No, it's to control access of users to images, in any situation, not just to avoid hotlinking.
> I assume that the point of this question is to avoid people
> linking to your images from other sites
No, it's to control access of users to images, in any situation, not just to avoid hotlinking.
> but the scripts of the images do NOT get reloaded, i.e. they behave as normal images.
Scripts of images? What are you talking about and what exactly is normal?
>No, it's to control access of users to images...
What sort of control are you talking about then?
Scripts of images? What are you talking about and what exactly is normal?
>No, it's to control access of users to images...
What sort of control are you talking about then?
When the user reloads your site, the images will be reloaded no matter what. There's no way to stop that. Use .htaccess to set a password on the file.
The image files I mean.
ASKER
>> but the scripts of the images do NOT get reloaded, i.e. they behave as normal images.
>Scripts of images? What are you talking about and what exactly is normal?
Sorry for crappy english!
The script of the page is a script that says something like this:
======== index.php ========
...
<body>
<img src="logo.gif">
<?
echo "This is your image";
echo "<img src="image.php"'>";
?>
</body>
...
The script of the image is something like this
======== image.php ========
...
$filename="somewhere.gif";
$size = getimagesize ($filename);
$fp = fopen($filename, 'rb');
header("Content-type: {$size['mime']}");
fpassthru($fp);
exit;
...
What I want is that when the user reloads (presses F5) index.php gets reloaded, but image.php does not get reloaded (just like logo.gif does not get reloaded)
this means image.php must be able to say "Status: 304 not modified" or what's the exact command
I hope this was more clear :-)
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Zyloch:
> the images will be reloaded
No, IMHO the images are reloaded if you press Shift-F5 (or something similar, depends on browsers)
the "default" reload will not reload images if tyour browser and the server are on the fact that the image has not changed.
> the images will be reloaded
No, IMHO the images are reloaded if you press Shift-F5 (or something similar, depends on browsers)
the "default" reload will not reload images if tyour browser and the server are on the fact that the image has not changed.
ASKER
Diablo84
> header("HTTP/1.0 304 Not Modified");
mmhh. you mean ALWAYS say that the contents has not changed, even if I do not know if it's in the users' cache??
That seems risky. I would be doing something VERY unexpected for the browsers, saynig them "as usual" even if they don't have the image.
> header("HTTP/1.0 304 Not Modified");
mmhh. you mean ALWAYS say that the contents has not changed, even if I do not know if it's in the users' cache??
That seems risky. I would be doing something VERY unexpected for the browsers, saynig them "as usual" even if they don't have the image.
The image file has to be downloaded once before the browser will have the header information so in theory it will do as you want, if the file has not beenn downloaded the browser wont have the header information.
The only issue i can see is if the image loading in image.php is dynamic in which case the purpose of the whole question is somewhat defeated.
The only issue i can see is if the image loading in image.php is dynamic in which case the purpose of the whole question is somewhat defeated.
Are you trying to put all our header suggestions in the image script file or the main file?
ASKER
What I found at http://www.phpbuilder.com/columns/brunner20011113.php3?page=3 is:
1) see if it's newer that the browser already has
if ($HTTP_IF_MODIFIED_SINCE == $gmt_mtime) {
header("HTTP/1.1 304 Not Modified");
exit;
}
2) otherwise send the contents but first inform the browser of the modification date
$lastmod_header = "Last-Modified: " . $gmt_mtime;
Header($lastmod_header);
....
For static files (ex. .GIF) this is automagically handled by apache.
for php this is left to us.
1) see if it's newer that the browser already has
if ($HTTP_IF_MODIFIED_SINCE == $gmt_mtime) {
header("HTTP/1.1 304 Not Modified");
exit;
}
2) otherwise send the contents but first inform the browser of the modification date
$lastmod_header = "Last-Modified: " . $gmt_mtime;
Header($lastmod_header);
....
For static files (ex. .GIF) this is automagically handled by apache.
for php this is left to us.
You can try this:
$gmtTime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
$allheaders = getallheaders();
if ($allheaders['If-Modified- Since'] == $gmtTime) {
header("HTTP/1.1 304 Not Modified");
exit;
}
$gmtTime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
$allheaders = getallheaders();
if ($allheaders['If-Modified-
header("HTTP/1.1 304 Not Modified");
exit;
}
ASKER
Diablo84:
> The only issue i can see is if the image loading in image.php is dynamic
well in this case, saying "not modified" would be a blatant lie!
Anyway, I will give a fast try to your aproach.
Zyloch:
>Are you trying to put all our header suggestions in the image script file or the main file?
No, the main file can stay as it is.
It's the images that I want to give proper headers (at the current rate, I would exceed 100GB per month, no host will support this without asking money! :-)
> The only issue i can see is if the image loading in image.php is dynamic
well in this case, saying "not modified" would be a blatant lie!
Anyway, I will give a fast try to your aproach.
Zyloch:
>Are you trying to put all our header suggestions in the image script file or the main file?
No, the main file can stay as it is.
It's the images that I want to give proper headers (at the current rate, I would exceed 100GB per month, no host will support this without asking money! :-)
another possibility i just thought of is setting the header expiration date in the future
eg.
$time = time() + 3600;
$gtime = gmdate('D, d M Y H:i:s', $time) . ' GMT';
header("Expires: $gtime");
3600 in this line is 3600 seconds
$time = time() + 3600;
obviously modify this for the amount of time you want to set it ahead
eg.
$time = time() + 3600;
$gtime = gmdate('D, d M Y H:i:s', $time) . ' GMT';
header("Expires: $gtime");
3600 in this line is 3600 seconds
$time = time() + 3600;
obviously modify this for the amount of time you want to set it ahead
for example you could set the expiration dates a week ahead so it would (again, in theory) only download the images once a week
$time = time() + 604800;
$gtime = gmdate('D, d M Y H:i:s', $time) . ' GMT';
header("Expires: $gtime");
$time = time() + 604800;
$gtime = gmdate('D, d M Y H:i:s', $time) . ' GMT';
header("Expires: $gtime");
Possible, but let's explore other avenues first
>am I just dumb?
See above comment.
>what should I do to save bandwidth?
Have you tried using session_cache_limiter("pub
http://us3.php.net/manual/en/function.session-cache-limiter.php