Photo Galleries with Mason and Imager
by Casey WestApril 01, 2004
Creating a photo gallery is usually considered a daunting task. Lots of people have tried it, not many have succeeded. One of the reasons for so many similar projects is that they don't often integrate well into an existing web site. In this article we're going to build a photo gallery using two important components, Mason and Imager. Writing our gallery in Mason will make it much easier to integrate into an existing web site.
Mason,
also known as HTML::Mason,
is a web application framework written in Perl.
Mason can run in any environment,
but is tuned to work best with mod_perl.
We will be using a number of Mason features in this article.
If you're not familiar with Mason I suggest you
get the book
or
browse
before you buy.
This article is not meant to be an introduction to Mason,
so some experience will definitely help when reading this.
Mason idioms will be briefly reviewed when they come up.
|
Related Reading
Embedding Perl in HTML with Mason |
Imager is a Perl module for dealing with images.
It has mechanisms to manipulate an image,
and read and write various formats.
It's rather lightweight and has a clean interface in comparison to the alternative,
Image::Magick.
Combining these two Perl modules, and adding a few others, allows us to write a feature-full photo gallery in just 200 lines. Let's get started.
Apache Configuration
We're going to use Mason from mod_perl for our gallery. This requires an Apache built with mod_perl, and bit of web server configuration.
First, Mason's Apache handler must be pre-loaded.
PerlModule HTML::Mason::ApacheHandler
Next, we need to tell Apache to let Mason handle any requests that it gets for resources within our gallery.
<Location /gallery>
SetHandler perl-script
PerlHandler HTML::Mason::ApacheHandler
</Location>
We want to keep special Mason files secret from the general public. If they're requested, Apache should always return a 404 HTTP status code, for Not Found.
<LocationMatch "(dhandler|autohandler)$">
SetHandler perl-script
PerlInitHandler Apache::Constants::NOT_FOUND
</LocationMatch>
At this point, every file inside the gallery will be considered a Mason component. If you enjoy paying for lots of bandwidth and you want the full-size images to be viewable by the public, one last configuration step must occur. The raw images are not Mason components so Apache should handle those in the default way.
<Location /gallery/images>
SetHandler default
</Location>
Directory Structure
For this article we'll use the following directory structure, in a directory called gallery, inside our site DocumentRoot.
.
|-- autohandler
|-- dhandler
|-- images
| `-- dhandler
|-- index.html
`-- pictures
`-- [lots of images and sub-directories]
As you can see, all the actual photos will be uploaded to the gallery/pictures directory. Our code will recognize sub-galleries and allow for infinite nesting. We can keep our photos very neatly organized this way.
As for the rest, it's all code. autohandler and dhandler are special Mason files, and index.html is just a wrapper around the top level dhandler.
The autohandler
For this example, our autohandler is extremely simple. I'm going to assume that you already have a Mason site running with your own autohandler wrappers in place. If you don't, you can use this one.
<%method .title>My Website</%method>
<html>
<head>
<title><& SELF:.title &></title>
</head>
<body>
<% $m->call_next %>
</body>
</html>
The first thing our autohandler does is define a subcomponent called .title. Mason subcomponents are wrapped in <%method> blocks. They are templates just like files; the only difference is they live inside the files. This is analogous to Perl files and subroutines.
Next we define the skeleton of the web page. The <title> tag's content is dynamically generated by the output of the SELF:.title subcomponent. Any time you want to call a subcomponent, the call is wrapped in <& &> delimiters.
The body, or content, of our web page will be provided by whatever component is next in the call stack. Using the global variable to access Mason object, $m, the call_next() method is executed to do just that.
In our gallery the next component in the call stack will be one of two files. If we're at the topmost level, http://example.com/gallery/, for example, index.html will be called. Everywhere else dhandler will be called. This is because no files exist for Mason to map to, and when that happens, Mason looks for a dhandler to execute.
The Invisible Index
dhandlers are default handlers for files inside a directory, and not that directory itself. Because of this we are required to provide an index.html file or Apache will attempt to display a directory listing, or possibly return a forbidden status code, if directory listings are not allowed. In reality, our index.html doesn't do anything at all.
In its entirety, index.html simply states that it inherits from dhandler. Now dhandler will be executed for all non-image access to our photo gallery.
<%flags>
inherit => 'dhandler'
</%flags>
This uncovers a portion of Mason's object-like component inheritance. By default, all components inherit from autohandler. For index.html we've changed that. dhandler still inherits from autohandler, so anytime a request is sent to index.html, dhandler is first called, which calls autohandler first. Then autohandler does its thing and moves down the call stack to dhandler. dhandler, as we'll see, is not configured to call down the stack to index.html, because it doesn't need to. Thus ends the very high-level overview of Mason inheritance.





