O'Reilly logo

Embedding Perl in HTML with Mason by Ken Williams, Dave Rolsky

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

The Main Features of Mason

There are more templating systems written in Perl than you could possibly keep in your head all at once. To help you make sense of Mason’s place in the world, this section presents Mason’s most important and distinctive features. By the end of this section, you should see that Mason pushes the boundaries of the term "templating system,” with lots of features aimed at helping you manage the larger tasks of site design and maintenance.

Components: Modular Design Elements

As we mentioned before, the basic unit of Mason code is called a component. It is a chunk of Mason code that can accept input parameters and generate output text. An important feature of Mason is that any component may call any other component at any point during its execution, much like a Perl subroutine calling another Perl subroutine. Because of this feature, a component may represent a single web page, a part of a web page (like a side navigation bar), or even a shared utility function that generates no output of its own. This separation of design elements allows you to use Mason as a sort of glorified server-side include (SSI) mechanism, as in Example 1-1, Example 1-2, and Example 1-3. Executing mainpage.mas will produce a full page of HTML with the header and footer inserted in place.

Example 1-1. header.mas

<html>
<head><title>Welcome to Wally World!</title></head>
<body bgcolor="#CCFFCC">

Example 1-2. footer.mas

<center><a href="/">Home</a></center>
</body></html>

Example 1-3 introduces the component call tag syntax, <& &>, which is used to call another component and insert its output into the surrounding text. The component tag can also accept arguments, which in this case can help unify site design by moving the page header text into the header.mas component.

Example 1-3. mainpage.mas

<& header.mas &>
<center><h1>Wally World Home</h1></center>
Here at Wally World you'll find all the finest accoutrements.
<& footer.mas &>

The header.mas component in Example 1-4 now accepts an argument called $head that contains the text that should get inserted into the <h1> tags. A component’s arguments are declared by using an <%args> block, which you’ll see in more detail later in the book. The $head argument becomes an honest-to-goodness Perl variable that can be used throughout the rest of the component. It’s lexically scoped in the header.mas component using Perl’s my( ) function.

Example 1-4. header.mas

<%args>
 $head
</%args>
<html>
<head><title>Welcome to Wally World!</title></head>
<body bgcolor="#CCFFCC">
<center><h1><% $head %></h1></center>

The footer.mas component in Example 1-5 is fairly straightforward. It just provides a link to the document root.

Example 1-5. footer.mas

<center><a href="/">Home</a></center>
</body></html>

In the mainpage.mas component in Example 1-6, the arguments are passed to the header.mas component by using standard Perl syntax (i.e., commas, quotes, and the => operator). In fact, any Perl syntax for passing a list can be used, because the argument list is specified in real Perl syntax.

Example 1-6. mainpage.mas

<& header.mas, head => "Wally World Home" &>
Here at Wally World you'll find all the latest accoutrements.
<& footer.mas &>

Mason will take the list of arguments passed to the header.mas component and assign the proper values to the variables specified in the <%args> block.

Object-Style Component Inheritance

Aside from the fact that there’s a little bit of Perl thrown into the mix for passing parameters, the examples we’ve seen don’t really show anything that you couldn’t do using standard server-side include (SSI) techniques. In fact, the usage demonstrated in these examples is relatively uncommon in building Mason sites, because there are better ways to get the job done. One of the greatest features of Mason is that components can inherit behavior from other components, much like classes and objects in an object-oriented hierarchy.[1] Typically, each component will inherit from a single component called the autohandler . The autohandler implements general behavior for all components, such as the content of headers and footers. Individual components implement specific behavior, such as the body text of the individual pages.

Using component inheritance, we can rewrite Example 1-4 through Example 1-6 in a more common Mason idiom, as shown in Example 1-7 and Example 1-8.

Example 1-7. autohandler

<html>
<head><title>Welcome to Wally World!</title></head>
<body bgcolor="#CCFFCC">
<center><h1><% $m->base_comp->attr('head') %></h1></center>
% $m->call_next;
<center><a href="/">Home</a></center>
</body></html>

Example 1-8. mainpage.mas

<%attr>
 head => "Wally World Home"
</%attr>
Here at Wally World you'll find all the finest accoutrements.

Notice that the header and footer are now both all in one file, the autohandler. Visually, this helps unify the page content, because tags like <html> and <body> that are opened in the header are closed in the same file. The other important difference here is that mainpage.mas no longer has to call the header and footer components explicitly, but rather Mason calls the parent component automatically and it wraps its header and footer around the main content. The page header is now specified by an attributes block, one of Mason’s object-oriented mechanisms. An attribute is a component property that inherits via Mason’s component inheritance chain.

There are zillions of other uses for Mason’s inheritance mechanism, which will be further explored in Chapter 5.

Intelligent Caching Mechanisms

Anyone who has built any dynamically generated web sites knows that sometimes certain portions of a site can take longer to generate and serve than you want to make your users wait. Furthermore, portions of a site might be only “semidynamic,” meaning that their content changes periodically but stays static for a long time between changes. Alternatively, as might happen on a news site or for an online poll, content may change continually, but a lag time of a few minutes in updating the content would be acceptable if it improves site performance. For cases like these, Mason provides a very sophisticated caching mechanism that you can use to control how often the output of a component is rebuilt. You can base the expiration decision on time, on certain key parameters like username or content ID, or on an explicit agent that decides when specific data has expired.

The caching mechanism can be used for the output of a component, for an arbitrary block of text, or for any Perl data structure you might want to cache. The first-class support for caching is one of Mason’s most endearing qualities, and you’ll learn to appreciate it the first time it saves you from spending hours optimizing sluggish code.

To aid overall performance, Mason also has an intelligent internal caching mechanism. During execution, Mason turns each component into Perl source code on disk, then compiles the Perl code into bytecode, then executes the bytecode to produce the component’s output. It would be a waste of computing resources to repeat this cycle every time a component needs to be executed, so Mason caches at each stage. As an aid to rapid development, Mason will check your components’ modification times and invalidate its cache when you make changes to your components, ensuring that any changes you make to your site take effect immediately. When your site moves from development to production, you probably won’t be making frequent changes to your site, so you can disable the freshness checks in order to improve your site’s responsiveness.

Integration with Apache and mod_perl

As mentioned before, the most common use of Mason is in building large, dynamic, data-driven web sites. The most popular web server around is Apache, and one of Apache’s most powerful features is mod_perl, which lets you use the full power of Perl within the Apache server process. Therefore, it should come as no surprise that Mason is designed to cooperate fully with mod_perl. Mason comes with drop-in mod_perl handlers that let Apache serve your Mason components directly. It lets you take advantage of the sophisticated decision-making mechanisms that Apache has evolved to support, such as custom authentication methods, content negotiation, and dynamic URL rewriting. Mason’s caching mechanism and other performance considerations are designed specifically for the task of serving dynamic content efficiently and with enough flexibility to let you design creative solutions to your specific problems. Although Mason lets you build a site without relying very much on assumptions about the server environment, learning about mod_perl and Apache’s request cycle can help you use Mason to create slick and powerful features.



[1] A caveat is necessary when using the term “object-oriented” to describe Mason’s content-wrapping and inheritance schemes, because Mason merely borrows some ideas from the object-oriented world rather than employing Perl’s (or any other language’s) built-in object-oriented inheritance.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required