Random Image

There are a number of way of implementing a random image using mod_perl. In the following example I’ll show you how to use the PerlResponseHandler Handler.

Setup

In this example I will be storing the images in a location that is not directly accessable by a user visiting your site.

I’ll assume that you have already configured your Apache server and that your web pages are stored in the htdocs directory. The domain used in this article is example.com.

I’ll start by creating three new directories.

  1. mkdir -p /var/www/example.com/htdocs/banners
  2. mkdir -p /var/www/example.com/images/banners
  3. mkdir -p /var/www/example.com/lib

/var/www/example.com/lib will be where we store our site’s mod_perl packages.

/var/www/example.com/images/banners will be where we store our images for this example.

Next we’ll activate the mod_perl Handler by creating /var/www/example.com/htdocs/banners/.htaccess

  1. Options +ExecCGI
  2. PerlSetEnv IMAGEBASEDIR /var/www/example.com/images/banners/
  3. SetHandler modperl
  4. PerlResponseHandler +MyApache2::Banners

We’ll also need some test images. Create a set of images beginning with header and ending in .jpg and place them in /var/www/example.com/images/banners, e.g. header1.jpg, header2.jpg, header3.jpg.

We’ll also have to tell Apache where our site’s perl packages are located. You will have to add the following line to either your httpd.conf file or at the top of you vhosts config file.

  1. PerlSwitches -I/var/www/example.com/lib

Code

We’ll create our Handler and call it /var/www/example.com/lib/MyApache2/Banners.pm

  1. package MyApache2::Banners;
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use Apache2::RequestRec ();
  7. use APR::Finfo ();
  8.  
  9. use Apache2::Const -compile => qw(DECLINED);
  10. use APR::Const -compile => qw(FINFO_NORM);
  11.  
  12. sub handler {
  13.     my $r = shift;
  14.  
  15.     if (exists $ENV{IMAGEBASEDIR} and $r->filename =~ m|^(.*/)(w+)(.w+)$|)
  16.     {
  17.         my ($p,$t,$s) = ($1,$2,$3);
  18.  
  19.         my $base = $ENV{IMAGEBASEDIR};
  20.         if (opendir( DIR, $base ))
  21.         {
  22.             my $regx = "^".$t.".*\".$s."$";
  23.             my @files = map {$base."$_"} grep {/$regx/} readdir DIR;
  24.             closedir DIR;
  25.  
  26.             if (scalar @files)
  27.             {
  28.                 my $n = int(rand($#files));
  29.                 my $filename = $files[$n];
  30.                 $r->filename($filename);
  31.                 $r->finfo(APR::Finfo::stat($filename, APR::Const::FINFO_NORM, $r->pool));
  32.             }
  33.         }
  34.     }
  35.  
  36.     return Apache2::Const::DECLINED;
  37. }
  38. 1;

The handler works by modifying the filename held in the Request. Line 15 performs two checks. The first is to check that we have setup a path to our images. The second detects that we are trying to retrieve a file, e.g. ‘/banner/header.jpg’. Line 17 extracts the filename prefix and extension, e.g. ‘header’ and ‘.jpg’. Lines 20-24 obtain a list of files in the $base directory that begin with $t and end in $s. Lines 28-29 select one of these files at random. Lines 30-31 update the request to use the random file. We need to update the filename and the cached file information in order for Apache to use the new file. We return Apache2::Const::DECLINED to indicate that the remaining Response Handlers need to be executed.

Problems

You may need to fix the ownership and permissions for the new directories and files.

  1. chown -R apache:apache /var/www/example.com/images
  2. chown -R apache:apache /var/www/example.com/htdocs/banners
  3. chown -R apache:apache /var/www/example.com/lib

Testing

Restart Apache and direct your browser to http://example.com/banners/header.jpg. If all went well you should be served one of the header image files from the /var/www/example.com/images/banners directory. Reloading the page (CTRL-R in FireFox) should result in another random image being served.

Final Words

As you may have noticed the code does not check that you are trying to request an image. The example code can be used to serve any type of file.

By using a PerlResponseHandler we are able to reuse the code in other parts of our site and control the source location of the files using our .htaccess files and the IMAGEBASEDIR environment variable.

No related posts.

Leave a Reply

You must be logged in to post a comment.