Introduction
Mason is a powerful Perl-based web site development and delivery engine. It cooperates fully with Perl, leveraging all the solutions and techniques that Perl developers depends on and that have made Perl such a powerful and widespread tool. Actually, Mason can be used to generate any sort of text, whether for a web site or not. But it was originally built for web sites and since that’s why most people are interested in it. Mason’s various pieces revolve around the notion of “components”. A component is a mix of HTML, Perl, and special Mason commands. Mason’s component syntax lets designers separate a web page into programmatic and design elements.
Mason works by intercepting requests and mapping them to requests for Mason components. Mason then compiles the component, runs it, and feeds the output back to the client.
Consider this simple Mason component:
[sourcecode language=”css”]
% my $user = "Sean Schofield";
Welcome <% $user %> !
[/sourcecode]
When Mason runs this code, the output is:
Welcome Sean Schofield!
Description:
The bare ‘%’ prefixing the first line tells Mason that this is a line of Perl code.The embedded tag gets replaced with the return value of its contents, evaluated as a Perl expression.
Getting Started with Mason
The requirements for installing HTML::Mason are:
* Perl 5.004 or later
* MLDBM
* Data::Dumper (included with recent Perl)
* Params::Validate
* Apache web server (recommended)
* mod_perl (recommended)
Apachetoolbox is a good way to get Apache and mod_perl installed.Install Apache with mod_perl. To make sure it is running, use the “printenv” CGI script to see what’s loaded. Then should see this somewhere in the output:
SERVER_SOFTWARE=”Apache/1.3.20 (Unix) mod_perl/1.25″
The above line will tell that Apache is running and that mod_perl is also running.Next we want to install the Perl modules on which Mason depends (MLDBM, Params::Validate, Data::Dumper). These are all easy modules to install. Go to http://search.cpan.org and search for the modules and download them.Untar the files: “tar -xzvf modulename.tar.gz” will usually do nicely.Then, to install the files, simply change to the directory and type:
perl Makefile.PL
make
make test
make install
Next, download and install the HTML::Mason module. The same steps are used to install this module as well. Once you have the HTML::Mason module installed, you need to make a few changes to your Apache config file (httpd.conf):
[sourcecode language=”css”]
PerlSetVar MasonCompRoot /usr/local/apache/htdocs/mason
PerlSetVar MasonDataDir /usr/local/apache/mason_data
<Location /mason>
SetHandler perl-script
PerlHandler HTML::Mason::ApacheHandler
</Location>
[/sourcecode]
These lines will tell Mason where the component root is. It will also tell where the Mason data directory is. This directory MUST be writable by the user that the web server runs under.This means that any file in this directory (or a subdirectory of it) will be served by Mason.
The Main Features of Mason
Following describes some of the important features of Mason
*Components: Modular Design Elements
*Object-Style Component Inheritance
*Intelligent Caching Mechanisms
*Integration with Apache and mod_perl
Components: Modular Design Elements :-Components are basically chunks of code that are reuseable by other HTML::Mason scripts.
Example:
Suppose that you want to put a welcome message that displays the date as a header to all the pages. Your header.html will look something like this:
[sourcecode language=”css”]
<%perl>
my @date = localtime;
my $hello = ‘Morning’;
if ($date[2] > 12 and $date[2] < 18) {
$hello = ‘Afternoon’;
} elsif ($date[2] >= 18) {
$hello = ‘Evening’;
}
</%perl>
Good <% $hello %> <br/>
Today is: <% $date[5] + 1900 %>/<% $date[4] + 1 %>/<% $date[3] %>
[/sourcecode]
All your pages have to include now is a call to the header component:
[sourcecode language=”css”]
<& header.html &>
[/sourcecode]
or
[sourcecode language=”css”]% $m->comp(‘header.html’);[/sourcecode]
Assuming you run this in the evening, this produces the following output:
Good Evening
Today is: 2012/1/12
Object-Style Component Inheritance :-All pages inherit from one file – usually known as ‘the autohandler’ lives in the ComponentRoot – ‘/autohandler’ (though may actually be more than one)
Example:
Without inheritance
header.mhtml
[sourcecode language=”css”]
<html>
<head><title>Welcome to the site</title></head>
<body>
[/sourcecode]
footer.mhtml
[sourcecode language=”css”]
</body>
</html>
[/sourcecode]
index.html
[sourcecode language=”css”]
<& header.mhtml &>
<h1>CONNECT, NETWORK, TRADE AND GROW</h1>
<p>Sell excess inventory, capacity or production to a new market of buyers locally & worldwide. Then, trade for the Products…</p>
<& footer.mhtml &>
[/sourcecode]
With inheritance
autohandler
[sourcecode language=”css”]
<html>
<head><title>Welcome to the site</title></head>
<body>
% $m->call_next();
</body>
</html>
[/sourcecode]
index.html
[sourcecode language=”css”]
<h1>CONNECT, NETWORK, TRADE AND GROW</h1>
<p>Sell excess inventory, capacity or production to a new market of buyers locally & worldwide. Then, trade for the Products…</p>
[/sourcecode]
The header and footer are now in the same file. $m->call_next() includes the contents from index.html. This helps
* unify the page content, because tags like <html> and <body>that are opened in the header are closed in the same file.
* no needlonger 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.
Intelligent Caching Mechanisms:-To aid overall performance.
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 as follows:
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. Mason will check components’ modification and invalidate its cache when make change to components, ensuring that any changes make to site take effect immediately.
Integration with Apache and mod_perl: 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.
Core Concepts
component : The component – a mix of Perl and HTML – is Mason’s basic building block and computational unit. Under Mason, web pages are formed by combining the output from multiple components.
component root: A component root is a directory or list of directories on the filesystem under which Mason expects to find all of your components.
component path:A component path can be thought of as a unique identifier for a particular component, in much the same way that a URL is a unique identifier for a particular resource.
Basic Component Syntax
Substitution Tags: Perl that is evaluated and sent as output
syntax:<% perl_code %>
Example:
[sourcecode language=”css”]
% $user = ‘Sean Schofield’ ;# this is embedded Perl
Hi <% $user %>! Welcome to the site .
[/sourcecode]
The output of this example would be:
Hi Sean Schofield! Welcome to the site .
Perl line : A single line of Perl code. A typical use of these lines is to implement Perl control structures.
syntax: % perl_code
Example:
[sourcecode language=”css”]
% my $ua = $r->header_in(‘User-Agent’);
% if ($ua =~ /msie/i) {
Welcome, Internet Explorer users
…
% } elsif ($ua =~ /mozilla/i) {
Welcome, Netscape users
…
% }
[/sourcecode]
Component call : A call to another component, possibly with arguments. The <& &> tag provides a convenient shortcut for $m->comp.
Syntax: <& perl_code &>
Example:
[sourcecode language=”css”]
<html>
<head>
<title> HTML::MASON Guide</title>
</head>
<body>
<h1>Welcome to HTML::MASON Guide Guide!</h1>
<& menu, width => 640, admin => 1 &>
</body>
</html>
[/sourcecode]
The menu component might contain a navigation bar used on all the pages for a site.
Named blocks : The following types of named blocks are supported
Perl block : If you have more than a few lines of Perl code in a row, however, it is probably best to use a Perl block instead of Perl line. A Perl block is equivalent to a bunch of Perl lines in a row.
Syntax: <%perl> perl_code </%perl>
Example:
[sourcecode language=”css”]
<%perl>
foreach my $person (@people) {
print "Name: ", $person->{name}, "\n";
print "Age: ", $person->{age}, "\n";
print "Height: ", $person->{height}, "\n";
print "Weight: ", $person->{weight}, "\n";
}
</%perl>
[/sourcecode]
}
init block : The Perl code it contains is run before any other code except for code in <%once> or<%shared> blocks. It is run every time the component is called.
Syntax :<%init> perl_code </%init>
Example:
The following template text will return a scheduled greeting
[sourcecode language=”css”]
Good <% $daypart %>.
<%init>
my $daypart = (localtime)[2]>11 ? ‘afternoon’ : ‘morning’;
</%init>
[/sourcecode]
args block: Defines a collection of variables to be initialized from named arguments passed to the subroutine. Arguments are separated by one or more newlines, and may optionally be followed by a default value. If no default value is provided, the argument is required and the subroutine will croak if it is not provided.The valid variable types are scalar, array, and hash, represented by their corresponding Perl sigil ($, @, or %).
Syntax : <%args> variable => default </%args>
Example:
[sourcecode language=”css”]
<%args>
$color
$size => 20 # A default value
@items => ( 1, 2, ‘something else’ )
%pairs => ( key1 => 1, key2 => ‘value’ )
</%args>
[/sourcecode]
doc block: Provides space for template developer documentation or comments which are not included in the output.
Syntax: <%doc> … </%doc>
Example:
[sourcecode language=”css”]
<%doc>
This is the part where I tell you what the component does.
</%doc>
[/sourcecode]
flags and attr blocks: These two blocks share the same syntax and are used to declare one or more key/value pairs. The key can contain only letters, numbers, and the underscore character ( _ ). The value can be any Perl expression whose results can fit into a scalar (such as a number, string, reference, or undef).The flags block may contain only official Mason flags, which are used to affect the component’s behavior.The attr block may contain any keys that you want.
Syntax:
For flags
<%flags> variable => default </%flags>
For attr
<%attr> variable => default </%attr>
Example:
[sourcecode language=”css”]
<%flags>
inherit => ‘/some/other/component’
</%flags>
<%attr>
color => "I’m so blue"
size => ‘mucho grande’
</%attr>
My color: <% $m->base_comp->attr(‘color’) %>
[/sourcecode]
def and method blocks: The def block contains a subcomponent, an embedded component that can be called via the normal Mason component calling syntax. A method block also contains an embedded component, but one that may be inherited by a component’s children.
Synatax:
For def
<%def .name_of_sub_component >
Any regular component syntax here…
</%def>
For method
<%method .name_of_sub_component >
Any regular component syntax here…
</%method >
Example:
[sourcecode language=”css”]
<perl>
<%def .breakURL>
<%args>
$url
</%args>
<%init>
my @parts = split ‘/’, $url;
return @parts;
</%init>
</%def>
</perl>
[/sourcecode]
Component Arguments
Most components will expect to receive named arguments, and these can be passed in one of two ways.
1.args block
2.%ARGS : This variable, always available, contains all of the parameters passed to the component (whether or not they were declared). It is especially used for dealing with large numbers of parameters, dynamically named parameters, or parameters with non-valid variable names. %ARGS can be used with or without an <%args> section, and its contents are unrelated to what you have declared in <%args>.
Using @_ : If you don’t like named parameters, you can pass a traditional list of ordered parameters:
[sourcecode language=”css”]
<& .row, contact => $contact, count => $count++, &>
[/sourcecode]
and access them as usual through Perl’s @_ array:
[sourcecode language=”css”]my ( $contact, $count) = @_;[/sourcecode]
In this case no <%agrs> section is necessary.
Special Globals
Two global per-request objects are available to all components: $r and $m.
$r : The mod_perl request object, provides a Perl API to the current Apache request.
Example:
[sourcecode language=”css”]my $c = $r->connection;[/sourcecode]
$m : This variable is an HTML::Mason::Request object, which has a number of methods that allow you to do things such as retrieve information on the current request, call other components, or affect the flow of execution
Example:
[sourcecode language=”css”]my $currentComp = $m->current_comp();[/sourcecode]
Special Components: Dhandlers and Autohandlers
Two powerful mechanisms that help lend reusable structure to your site and help you design creative solutions to unique problems.
dhandlers
The term ” dhandler” stands for “default handler.” The concept is simple: if Mason is asked to process a certain component but that component does not exist in the component tree, Mason scans backward through the URI, checking each directory for a component named dhandler. If found, the dhandler is invoked and is expected to use $m->dhandler_arg as the parameter to some access function, perhaps a database lookup or location in another filesystem.
Mason looks for dhandlers in the apparent requested directory and all parent directories. For instance, if your web server receives a request for /members/2012/April/12 and passes that request to Mason, but no such Mason component exists, Mason will sequentially look for /members/2012/April/dhandler,/members/2012/dhandler,/members/dhandler, and /dhandler. If any of these components exist, the search will terminate and Mason will serve the first dhandler it finds, making the remainder of the requested component path available to the dhandler via $m->dhandler_arg. For instance, if the first dhandler found is /members/dhandler, then inside this component (and any components it calls), $m->dhandler_arg will return 2012/April/12. The dhandler can use this information to decide how to process the request.
autohandlers
Autohandlers allow you to grab control and perform some action just before Mason calls the top-level component. This might mean adding a standard header and footer, applying an output filter, or setting up global variables.
Autohandlers are directory based. When Mason determines the top-level component, it checks that directory and all parent directories for a component called autohandler. If found, the autohandler is called first. After performing its actions, the autohandler typically calls $m->call_next to transfer control to the original intended component.
$m->call_next works just like $m->comp except that the component path and arguments are implicit. You can pass additional arguments to $m->call_next; these are merged with the original arguments, taking precedence in case of conflict. This allows you, for example, to override arguments passed in the URL.
Example:
Here is an autohandler that adds a common header and footer to each page underneath its directory:
[sourcecode language=”css”]
<html>
<head><title>E-commerce</title></head>
<body style="background-color: blue">
% $m->call_next;
<hr />
Copyright © 2003 – 2012.
</body>
</html>
[/sourcecode]
dhandlers vs. autohandlers
dhandlers and autohandlers both provide a way to exert control over a large set of URLs. However, each specializes in a very different application. The key difference is that dhandlers are invoked only when no appropriate component exists, while autohandlers are invoked only in conjunction with a matching component.
Most important about the way dhandlers and autohandlers interact is that Mason first figures out how to resolve a path to a component name, then figures out the inheritance of that component. In other words, Mason determines dhandlers before it determines autohandlers. This has several consequences.
First, it means that a dhandler may use the inheritance mechanism just like any other component can. A component called /account/dhandler may specify its parent using the inherit flag, or it may inherit from /account/autohandler or /autohandler by default.
Second, if Mason receives a request for /commerce/exchange_items/search.mas, and the component root contains components called /commerce/exchange_items/autohandler and /exchange_items/dhandler but no /commerce/exchange_items/search.mas, Mason will first determine that the proper requested component for this request is /commerce/dhandler, then it will search the component root for any appropriate parents. Since the autohandler is located in the /commerce/exchange_items/ directory, it won’t be invoked when serving /commerce/.
In short, Mason itself is sort of a unique offering. It sits somewhere in the middle between lightweight and heavyweight solutions. It doesn’t directly provide support for database connections, HTML munging, or sessions, but it makes it so easy to use regular Perl tools for these purposes that will never miss the functionality. In a sense, Mason’s main strengths lie in the ways it lets you interface various parts of your site with one another and with outside resources.