Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Trouble Caching an Image

by Baz (Friar)
on Sep 04, 2002 at 21:00 UTC ( [id://195204]=perlquestion: print w/replies, xml ) Need Help??

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

Hers my code -
#!/usr/bin/perl $lifetime = 2*60 ; # image expiry time # load the HTTP date routines $libloc = "/usr/local/lib/libwww-perl-0.40" ; unshift(@INC, $libloc); require "timelocal.pl" ; require "wwwdates.pl" ; $path = $ENV{'PATH_INFO'} ; $query = $ENV{'QUERY_STRING'}; $pragma = $ENV{'HTTP_PRAGMA'} ; $pragma =~ tr/A-Z/a-z/ ; $imsd = $ENV{'HTTP_IF_MODIFIED_SINCE'} ; $ims = $imsd ; $ims =~ s/;.*// ; # for Netscape $ims = &wwwdates'get_gmtime($ims) ; $file = "./shut.jpg" ; # find the modification time of the cached image and work out # its age #if ($ims && $modtime<=$ims) { # print "Content-type: text/plain\n\nError opening file\n"; # print "Status: 304 Not Modified\n\n" ; # exit ; #} # set expiry time. Agents will automatically load a new image # if their cached version is older than this. $expires = time + $lifetime ; # Convert expiry and last-modified times to RFC1123 time $gexpires = &wwwdates'wtime($expires,'GMT'); $glastmod = &wwwdates'wtime($modtime ,'GMT'); open (JPG,$file) ; $jlen = read (JPG,$doc,50000) ; if (!$jlen) { print "Content-type: text/plain\n\nError opening file\n"; exit ; } # Generate the complete HTTP response for a successful GET print "Content-type: image/jpeg\n"; print "Last-Modified: $glastmod\n"; print "Expires: $gexpires\n"; print "Content-Length: $jlen\n"; print"\n"; print "$doc";
The first time I run this from my browser, the image displays fine, but if I hit reload (on IE6 or NS) I get Internal Server Error. If I hit back then forward, the image reappers - its loaded from the cache as there is no download pause.

I wish to start playing around with "Status: 304 Not Modified"(commented out at the moment) as I'm trying to cache SVGs and ive been informed that I'll need this to get IE to work - the guy who's giving me advice doesnt script in perl so I'm leaving my code as simple as possible - hence no CGI.
Any ideas as to what I'm doing wrong?
thanks,
Barry.

Replies are listed 'Best First'.
•Re: Trouble Caching an Image
by merlyn (Sage) on Sep 04, 2002 at 23:06 UTC
    Is there any reason you can't just replace the whole thing with:
    print "Location: /internal/web-path/to/shut.jpg\n\n";
    possibly regenerating shut.jpg if it's too much out of date?

    Then you get the if-modified-since logic for free, as well as the chunking and mod-time printing.

    Internal redirects can be very cool, and are far too much underutilized. CGI is not the only interface. {grin}

    -- Randal L. Schwartz, Perl hacker

Re: Trouble Caching an Image
by dws (Chancellor) on Sep 04, 2002 at 21:42 UTC
    A couple of suggestions:

    First, use strict; at the top of the module will keep you out of a lot of trouble.

    Next, use CGI; and using it to parse URLs and forms will keep you out of even more trouble. "As simple as possible" is not a good argument. The code you provided would be shorter if you used CGI. (If you're worried about performance, consider CGI::Lite.) In this case, never mind.

    Next, if you're running a current (or nearly current) Perl distribution, the date manipulation routines you need should be included, saving you the trouble of lugging around custom methods of uncertain ancestry.

    Try something like the following fragment:

    use HTTP::Date qw(time2str); my $now = time2str($filetime); my $expires = time2str($filetime + $delta); print "Last-modified: $now\n"; print "Expires: $expires\n";
    Finally, one of the subtle problems you'll have is that getting expire times to work depends on a couple of things that might be out of your control.

    • The server's clock needs to be set at (or adjustable to) GMT. Expire times are expressed in GMT.
    • The browser needs to be set to honor the Expires header. (It's possible to configure most browsers to ignore them, and Cache-Control headers, and refetch every time.)
    • The browser's clock needs to be consistent with the server's clock. Good luck here.

    Treat setting the Expires header as an optimization, and be prepared to have it ignored.

      Thanks, I replaced that code and it works now (I was just using a script I found on the web - I'm trying to get my head around 304 and this script included it). Anyway, I've added in the 304 part and that loop is now entered on subsequent calls - which is what I want. Now I need to get it working for SVG, which will be fun...
Re: Trouble Caching an Image
by perrin (Chancellor) on Sep 04, 2002 at 21:07 UTC
    Well, what's the error you're getting? It must say something in the log about what caused your script to die when you hit reload.
      Your right, sorry about that, the error loaded so quickly that I didn't think it was server related.
      Heres that error, from the log -
      Undefined subroutine &wwwdates::timegm called at wwwdates.pl line 211. [Wed Sep 4 17:17:18 2002] [error] [client 194.165.165.171] Premature +end of script headers: /home/baz/public_html/ww.cgi
        Okay, so the error is actually coming from code that you aren't showing here, in the wwwdates.pl script.

        Just a guess: are you running this under Apache::Registry?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://195204]
Approved by VSarkiss
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-24 05:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found