Solved

cache friendliness and HTTP_IF_MODIFIED_SINCE

Posted on 2004-08-04
24
408 Views
Last Modified: 2012-06-27
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?

0
Comment
Question by:frox
  • 9
  • 7
  • 4
  • +3
24 Comments
 
LVL 36

Accepted Solution

by:
Zyloch earned 200 total points
ID: 11715759
If-Modified-Since is not a predefined PHP header, and it's a request header, so it'll be useless for you. You can try this:

<?php
header('Cache-Control: only-if-cached');
?>

Regards,
${Zyloch}
0
 
LVL 33

Expert Comment

by:snoyes_jw
ID: 11715800
>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
0
 
LVL 16

Expert Comment

by:hankknight
ID: 11715873
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.
0
 

Author Comment

by:frox
ID: 11715939
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.
0
 
LVL 36

Expert Comment

by:Zyloch
ID: 11716001
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.
0
 

Author Comment

by:frox
ID: 11716005
For  snoyes_jw:

Also

<?php
session_cache_limiter("public");
echo time();
?>

still shows the seconds that change.

0
 
LVL 36

Expert Comment

by:Zyloch
ID: 11716014
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.
0
 

Author Comment

by:frox
ID: 11716091
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)
0
 
LVL 33

Expert Comment

by:snoyes_jw
ID: 11716112
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
0
 

Author Comment

by:frox
ID: 11716160
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.
0
 
LVL 2

Expert Comment

by:TaintedGod
ID: 11716627
> 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?
0
 
LVL 36

Expert Comment

by:Zyloch
ID: 11716997
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.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 36

Expert Comment

by:Zyloch
ID: 11717002
The image files I mean.
0
 

Author Comment

by:frox
ID: 11717041

>> 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 :-)
0
 
LVL 27

Assisted Solution

by:Diablo84
Diablo84 earned 200 total points
ID: 11717122
you could try

header("HTTP/1.0 304 Not Modified");

in image.php

ie.

  $filename="somewhere.gif";
  $size = getimagesize ($filename);
  $fp = fopen($filename, 'rb');
  header("Content-type: {$size['mime']}");
  header("HTTP/1.0 304 Not Modified");
  fpassthru($fp);
  exit;
0
 

Author Comment

by:frox
ID: 11717130
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.

0
 

Author Comment

by:frox
ID: 11717176
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.
0
 
LVL 27

Expert Comment

by:Diablo84
ID: 11717212
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.
0
 
LVL 36

Expert Comment

by:Zyloch
ID: 11717219
Are you trying to put all our header suggestions in the image script file or the main file?
0
 

Author Comment

by:frox
ID: 11717225
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.
0
 
LVL 36

Expert Comment

by:Zyloch
ID: 11717274
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;
}
0
 

Author Comment

by:frox
ID: 11717278
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! :-)

0
 
LVL 27

Expert Comment

by:Diablo84
ID: 11717311
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
0
 
LVL 27

Expert Comment

by:Diablo84
ID: 11717343
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");
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now