campbell has asked for the wisdom of the Perl Monks concerning the following question:

Greetings

This is a follow-up to a previous problem I posted in SOPW (see Use of GD::Graph).

Having successfully implemented the solution proposed to me (i.e. printing images to file, and then calling them back from file using tags), I am now finding that the images, rather than being updated when I click the submit button in my form, are only being updated when I hit the refresh button in my browser. I suspected this was something to do a web-server or proxy cache-ing the web page somewhere along the line, so I put the following line in my code to print to the HTTP header :

print "Cache-Control: no-cache\n";

My local webmaster also tells me that the web-server is not doing any cacheing. However, inserting this line did not solve the problem and I suspect that there is something erroneous going on with writing to and retrieving from the files.

Here are the relevant parts of my code:

#!/usr/bin/perl -w use strict; use warnings; use CGI qw/:standard *table *Tr *td/; use CGI::Carp qw(fatalsToBrowser); use Date::Manip; use DBI; use GD::Graph; use GD::Graph::bars; use GD::Graph::lines; use GD::Graph::linespoints; my $image_directory="/var/www/html/foo/bar/"; my $image_web_path="http://(IPaddress here)/foo/bar/"; print "Cache-Control: no-cache\n"; print header; print start_html( -title=>'Online search', -style=>'(link to style sheet)' ); my @imagefiles; for (my $i=1; $i<=8; $i++){$imagefiles[$i]=$image_directory.'imagefile +'.$i.'.gif';} ... (form to acquire parameters specifying beginning and ending of search +period) ... (database interrogation based on above search period, writing data to +various data structures, then preparing the data to be processed by G +D::Graph) ... #Output the results of the database interrogation as a graph using GD +::Graph and write it to file like so: open IMAGEFILE, ">$imagefiles[6]" or die "Couldn't open $imagefile +s[6]:$!"; binmode STDOUT; my $gd3_lines_average=$linegraph3_average->plot(\@linedata3_averag +e)->$format3_lines_average() or die $linegraph3_average->error; print IMAGEFILE $gd3_lines_average; close IMAGEFILE; ... Create the other image files in a similar way to the one above ... print img({-src=>$image_web_path.'imagefile6.gif',-width=>"400",-heigh +t=>"300",-alt=>"No of foos in month bar"}) ... Retrieve the other image files in a similar way to the one above ... print end_html;
I've also tried retrieving the images as local files but to no avail. I could implement the second solution that was proposed to me, i.e. passing the form parameters to a second Perl script that output the images on the fly, but having gone down this route I would like to at least have a go at solving this problem before I do so.

Any ideas as to what's going on?

Thanks in advance,
Campbell

Replies are listed 'Best First'.
Re: Web server cache-ing?
by almut (Canon) on May 22, 2008 at 12:37 UTC
    the images, rather than being updated when I click the submit button in my form, are only being updated when I hit the refresh button

    You haven't shown your form, in particular what action URI it submits to, and how you're handling the respective request on the server side. Also, under some circumstances, it could make a difference whether you use the HTTP method GET or POST.

    First step would be to look in the webserver's access log to see if the request is actually coming in and what the server's HTTP response code is...

    Update: or is your problem rather that you modify the images' content, but try to serve them under the same name/URI?  In that case, appending some dummy parameter to the image URIs, which changes from request to request (e.g. the current time)

    $image_web_path.'imagefile6.gif?t='.time()

    could get you around unwanted caching...

      Making sure that the URL of the image changes is of course a good idea.

      However, as the content of the image changes, would it not be much more logical to change the filename, rather than adding a dummy parameter?

      Security wise it would also stop anyone from "stealing" images to which he should have no access, by simply directly requesting $image_web_path.'imagefile6.gif over and over again.Using a module such as Data::UUID can give you a unique identifier everytime you ask for one. If you clean the server-side "cache" of your files on a regular basis, it becomes almost impossible to guess the file name of any of the files in the cache, thus protecting the contents of these graphic files. The actual odds of guessing right would be 1 / (2^128) times the number of files (or better than 1 in 30 million300 billion billion billion billion times the number of files) in your cache.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Update: or is your problem that you modify the images' content, but try to serve them under the same name/URI? In that case, appending some dummy parameter to the image URIs, which changes from request to request (e.g. the current time)

      Yes, of course! That works nicely - Thank you.

      (campbell goes off to flagellate himself in the penance room)

        No reason to flagellate yourself :) — it's not your fault, but the browser's, applying half-legal heuristics to determine when to ask the server if the image has been updated... (performance being the motivation behind it, relying on the 'typical case').

Re: Web server cache-ing?
by moritz (Cardinal) on May 22, 2008 at 13:06 UTC
    Adding the cache-control header doesn't help because it's probably the images that are being cached, not the HTML page. And the header only affects the object that is being transfered with it (in this case the HTML), not the objects that are referenced in that document.

    Open one of the images in a tab (or window) of its own. Then request the HTML page from your server, and then reload the image separately (in Firefox with Shift+Control+R) . Does the image get updated?

Re: Web server cache-ing?
by Anonymous Monk on May 22, 2008 at 12:26 UTC
    if there is any caching, it is your browser thats doing it