http://qs1969.pair.com?node_id=55767

Item Description: Embed Perl code in Web pages with component architecture

Review Synopsis:

In honor of Mason's 1.0 release I thought I'd submit a quick review.

This is one of my favorite Perl modules, and my tool of choice for creating Web pages. Mason is developed by Jonathan Swartz and a large number of other contributors. It was created originally for CMP Media, publishers of TechWeb.com and a wide variety of other sites; since then it has been put in use at a number of high-profile sites such as Salon.com and AvantGo.com, not to mention hordes of lower traffic places.

Embedding Perl in HTML

Anyone who's perused the HTML:: namespace on CPAN knows that there are a number of tools to choose from in putting Perl into Web pages. Among that list of choices, Mason is unique, just like all the rest :).

Mason is first and foremost a Perl embedding tool; that is, it inserts Perl code directly into pages, to be interpretted on the fly as documents are served. This distinguishes it from the "template" camp of tools that separate documents and code; I won't get into the argument over which is better, but if you work on both document content and code together, you'll probably prefer an embedding tool. Other choices in this camp include HTML::EmbPerl and Apache::ASP.

Mason adds a few new tags to tell its interpretter where to find Perl code. To evaluate a single line of Perl, preface it with a % at the beginning of the line:

% my $date = localtime();
To interpolate a Perl variable or expression into other text, surround it with the <% % > tag:
Today's date is <% $date %>
% lines can also be used to create conditional sections, or to build text using loops. To borrow two examples from the docs:
% my $ua = $r->header_in('User-Agent'); % if ($ua =~ /msie/i) { Welcome, Internet Explorer users % } elsif ($ua =~ /mozilla/i) { Welcome, Netscape users % }

% foreach $item (@list) { <li><% $item %> % }
Longer pieces of code can be set off using <%perl> sections, where all statements up to the ending </%perl> are interpretted as code.

Component architecture

Mason's code embedding is nice, but the module really shines when used to build documents from pieces.

In Mason, sections of pages are components. A top-level component corresponds to a document, and can contain all the content and Perl code directly. More likely though, the top-level refers to other components via the component call tag, <& &>. For example, suppose we have a page layout consisting of a header component, a navigation bar, a footer and what ever text the page contains. A top-level for that design would look like this:

<& header &> <& nav-bar &> Here is the content of this page. <& footer &>

Passing arguments to components

But wait, there's more! The top-level component automatically receives any CGI parameters passed along with the request as arguments; it can also pass parameters along to any invoked component, which can in turn pass info along to any components they use.

To invoke a component with arguments, pass them along inside the tags:

<& header, date=>$date, section=>'News' &>
To receive those values, the component needs an <%args> section:
<%args> $date $section=>'Updates' </%args>
In this example, the date argument is required to have a value when the component is invoked; the section argument has a default value, and can be omitted.

Autohandlers and dhandlers

Mason provides two mechanisms for additional standardization.

Autohandlers are components that run before the top-level component; they can be used to provide a standard set of header/footer components or enforce other site rules. Mason checks the top-level component's directory (and all of its parents) for an autohandler and runs it before the code in the top-level itself.

dhandlers take the place of a component that doesn't exist. This is most commonly used to replace top-level components requested by a generated URL; if Mason doesn't find the requested component, it checks the directory (and its parents) for a dhandler and runs that instead. The dhandler can look at the request URL and figure out what to do, such as retrieving the actual requested document from a database.

Caching

Behind the scenes, Mason translates a component into a Perl function and calls it; text in the component becomes literal values stored in the function, while the embedded code moves into the function more or less as-is. Mason caches the translated code in a separate directory for better run-time performance. As requests occur and components are called, Mason checks the modification times of its cache and the actual component file; if nothing has changed, it just uses the cache.

Used in conjunction with mod_perl, this provides excellent performance, but those stat calls for checking times still add up. You can improve Mason's speed by telling it to check only a single file (the reload file) for updates, and then store the paths to changed components in that file as you modify them.

And more...

Mason has far too many features to do justice in a short review. A quick list of things to look for in the documentation: Take a look at the Mason Headquarters for more information.

2001-03-04 Edit by Corion : Changed PRE tags to CODE tags.