FastCGI: Persistent Applications for Your Web Server

Listing 1. rotate.fcg Script

#!/usr/bin/perl -w
# rotate.fcg -- a script to rotate sponsor ads.
use FCGI;
# The QUERY_STRING is expected to be the name of
# an HTML file in the following directory
my $DOCROOT = "/path/to/files";
# Scope the array that we'll use throughout
# the life of the script.
my @ads = (); # array of ads
# Initialize the %ENV hash so it's not empty...
while (my($key, $val) = each %ENV) { next }
# Force flush after each 'print()'
$| = 1;
# Initialize the array of ads
@ads = initialize();
#
# Now the main show
REQUEST: while (FCGI::accept() >= 0) {
 # Catch valid requests to reinitialize
 if ($ENV{QUERY_STRING} eq 'reload' and
 $ENV{REMOTE_ADDR} =~ /^127\.0\.0/)
 {
 @ads = initialize();
 next REQUEST;
 }
 # Make sure we can open the file. If not, tell
 # the user and wait for the next REQUEST.
 unless (open(DOC, "$DOCROOT/$ENV{QUERY_STRING}"))
 {
 file_not_found();
 next REQUEST;
 }
 # Put file into an array, where we can do some
 # text substitutions.
 my @doc = <DOC>;
 close DOC;
 # Get first $ad in line, then move it to the
 # back.
 $ad = shift @ads;
 push @ads, $ad;
 # Look for '<!-- Ad Here -->' and put one
 # there while sending @doc off.
 print
 "Content-type: text/html",
 "\r\n\r\n",
 map { s/<!--\s*Ad\s+Here\s*-->/$ad/i } @doc;
}
# ----- Initialization subroutine -----
sub initialize {
 my @ads = ();
 # Set the input record separator to null
 # because we rely on multi-line records
 $/ = "";
 # If we can't find the data file, we'll page
 # the admin and return an empty array; the
 # script will still be able to function.
 unless (open(SPONSORS, "/pathto/sponsors.txt"))
 {
 page_sysadmin();
 return ();
 }
 foreach my $entry (<SPONSORS>) {
 # Put the data into a hash for easy
 # lookup.
 my %sponsor = ();
 foreach my $datum (split(/\n/, $entry)) {
 my ($key, $val) = split(/=/, $datum, 2);
 $key = lc $key; # just in case
 $sponsor{$key} = $val;
 }
 # Format the ad in HTML and push it into
 # @ads.
 push @ads, join( '',
 qq(<A HREF="$sponsor{url}">),
 qq(<IMG SRC="$sponsor{image}" ),
 qq(ALT="$sponsor{description}" ),
 qq(WIDTH=$sponsor{width} ),
 qq(HEIGHT=$sponsor{height} ),
 qq(BORDER=$sponsor{border}>),
 qq(</A>)
 );
 }
 # Clean up after ourselves.
 close SPONSORS;
 $/ = "\n";
 return @ads;
}
# Other functions would follow.

AltStyle によって変換されたページ (->オリジナル) /