Link to home
Start Free TrialLog in
Avatar of frox
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?

ASKER CERTIFIED SOLUTION
Avatar of Zyloch
Zyloch
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>problem of the apache configuration??
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("public")?

http://us3.php.net/manual/en/function.session-cache-limiter.php
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.
Avatar of frox
frox

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.
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("public") which allows the user's machine to cache.
Avatar of frox

ASKER

For  snoyes_jw:

Also

<?php
session_cache_limiter("public");
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.
Avatar of frox

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)
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
Avatar of frox

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.
> 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?
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.
Avatar of frox

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
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of frox

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.

Avatar of frox

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.
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.
Are you trying to put all our header suggestions in the image script file or the main file?
Avatar of frox

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.
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;
}
Avatar of frox

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! :-)

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
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");