=head1 NAME

HTML::Mason FAQ - frequently asked questions about HTML::Mason

=head1 DESCRIPTION

HTML::Mason is a perl-based web site development and delivery engine.
This document is designed to answer questions that arise when using
HTML::Mason to develop new and convert existing applications.

=head1 QUESTIONS & ANSWERS

=head2 What is HTML::Mason?

HTML::Mason is a Perl-based web site development and delivery engine.  In
addition to supporting embedded Perl in HTML pages, HTML::Mason provides
facilities for many common web development issues: templating, caching,
debugging, profiling, page previewing, and more. Although it can be used
with CGI or even stand-alone, HTML::Mason works best in conjunction with
Apache and mod_perl.

=head2 Does HTML::Mason have an official web site?

Yes, at http://www.masonhq.com.

=head2 Where do I obtain HTML::Mason?

HTML::Mason is available from CPAN (the Comprehensive Perl Archive Network).
Details about CPAN are available at http://www.perl.com/.

=head2 What else do I need to use HTML::Mason?

If you are planning on using HTML::Mason in a web environment with the
Apache webserver, you'll need a working copy of Apache and mod_perl
installed.  Make sure that your mod_perl installation works correctly before
trying to get HTML::Mason working.  Also, if you are running RedHat Linux, 
B<do not> use the mod_perl RPMs that ship with RedHat.  They are not
reliable (as of RedHat 6.1/mod_perl 1.21).

=head2 Where can I ask questions about HTML::Mason or report bugs?

You are encouraged to use the HTML::Mason mailing list; that way many people
can answer questions and/or benefit from the answer. Write to
mason@netizen.com.au.  You may want to browse past messages in the archive
first.  Go to http://netizen.com.au/mailman/listinfo/mason for more
information or to subscribe (although you can post without being
subscribed).

If the question is more generally about mod_perl, you may wish to post 
additionally (or only) to the mod_perl mailing list at modperl@apache.org.

If you have a question or comment that you don't feel is appropriate for the
group, write to swartz@transbay.net.

=head2 What is a component?

A component is a file that contains some combination of text (typically
HTML), perl code and HTML::Mason directives.

Some components are accessed directly by web browsers.  These are called
top-level components.  A top-level component might consist purely of static
HTML.

Other components are support components, which are called by top-level
components or other support components.  These components are analogous to
perl subroutines -- they allow you to create small packages of code that you
can reuse throughout your project.

=head2 How do components communicate with each other?

Components can return values to their callers, just like subroutines.

Some components may have very simple return values.  As an example, consider
a component called isNetscape which returns a true value when the client's
browser is Netscape and undef when it is not.  The isNetscape component
could then be used easily in an if() or other control statement.

Of course, components can also return strings of text, arrays, hashes or
other arbitrarily complex perl data structures.

=head2 How do I use modules in components?

Technically you can just say "use module-name" at the beginning of a
component.  The disadvantages of this method are that:

=over 4

=item *

the module will be used separately by every httpd child process, costing
both time and memory.

=item *

it is difficult to keep track of all the modules being used on a site.

=back

A more efficient method is to put the use line in the handler.pl or use the
PerlModule directive.  If you want components to be able to refer to symbols
exported by the module, you need to use the module inside the
HTML::Mason::Commands package.  See the "External modules"
section of the Administrator's Guide:

	http://www.masonhq.com/docs/manual/0.8/Admin.html#external_modules

=head2 Can I define subroutines in components?

First, consider using a separate component. They are functionally
equivalent, and this is playing to Mason's strengths.  If the
subroutine is small, or limited in scope, consider using a <%def>
subcomponent.

You can define named subroutines inside the <%once> section of any
component.  Defining the subroutine in a <%perl> or <%init> section is
not reliable because such a definition would end up residing inside
another subroutine, and Perl doesn't like that.

You can define anonymous subroutines anywhere:

	my $foo = sub {...};

=head2 Can I serve images through a HTML::Mason server?

If you put images in the same directories as components, you need to make
sure that the images don't get handled through HTML::Mason.  The reason is
that HTML::Mason will try to parse the images and may inadvertently find
HTML::Mason syntax (e.g. "<%").  Most images will probably pass through
successfully but a few will cause HTML::Mason errors.

The simplest remedy is to have HTML::Mason decline image and other non-HTML
requests, thus letting Apache serve them in the normal way.  The following
line, placed in the handler() subroutine of your handler.pl,

	return -1 if defined($r->content_type) && $r->content_type !~ m|^text/|io;

declines all requests with a content type not starting with "text/". This 
allows text/html and text/plain to pass through but not much else. It is 
included in the default handler.pl.

Another solution is to put all images in a separate directory; it is then
easier to tell Apache to serve them in the normal way.  See the next
question.

For performance reasons you should consider serving images from a completely
separate (non-HTML::Mason) server. This will save a lot of memory as most
requests will go to a thin image server instead of a large mod_perl server.
See Vivek Khera's performance FAQ for a more detailed explanation.

=head2 How can I prevent a particular subdirectory from being handled by HTML::Mason?

Suppose you have a directory under your document root, "/plain", and you
would like to serve these files normally instead of using the HTML::Mason
handler. One solution is to use a Location directive like:

	<Location /plain>
		SetHandler default-handler
	</Location>

Apparently these will work as well:

	SetHandler text/html
	SetHandler */*

Another solution is to put a line like this at the top of the handler() 
subroutine of your handler.pl:

	return -1 if $r->uri() =~ m|^/plain|;

=head2 Is Mason fast?

It is typically more than fast enough.  50-100 requests per second for a
simple component is typical for a reasonably modern Linux system.  Some
simple benchmarking indicates that a Mason component is typically about two
to three times slower than an equivalent, hand-coded mod_perl module.

Beware of "Hello World!" and other simple benchmarks.  While these
benchmarks do a good job of measuring the setup and initialization time for
a package, they are typically not good measures of how a package will
perform in a complex, real-world application.  As with any program, the only
way to know if it meets your requirements is to test it yourself.

In general, however, if your application is fast enough in pure mod_perl, it
will most likely be fast enough under HTML::Mason as well.

=head2 How can I make my Mason application run faster?

The first thing you can do to optimize Mason performance is to optimize your
mod_perl installation.  Consider implementing some of the tuning tips
recommended in mod_perl_tuning, which ships with every copy of mod_perl.

If your application still needs to run faster, consider using Mason's
caching methods ($m->cache and $m->cache_self) to avoid regenerating
dynamic content unnecessarily.

=head2 Does Mason leak memory?

The last known Mason-specific leak was fixed in 0.5.  We are not aware of
any current leaks in Mason itself. If you are using RedHat's mod_perl RPM,
or another DSO mod_perl installation, you will leak memory and should switch
to a statically compiled mod_perl.

Of course it is always possible for your own component code to leak, e.g.
by creating and not cleaning up global variables.

=head2 Can I run HTML::Mason outside a web server?

Yes, in fact HTML::Mason can be useful for generating a set of web pages
offline or as a general templating tool.  See the "Standalone Mode"
section of the Interpreter manual:

	http://www.masonhq.com/docs/manual/0.8/Interp.html#standalone_mode

=head2 Can I run HTML::Mason via CGI?

Yes.  Masonite Ilmari Karonen uses HTML::Mason under CGI.  He has kindly
posted the necessary steps to do this on the HTML::Mason mailing list.  His
message can be viewed at http://forum.swarthmore.edu/epigone/mason/gimpswumfrex/Pine.SOL.3.96.990917144751.17640B-100000@simpukka

Please note that running HTML::Mason under CGI (or other non-persistent
environments) will entail a substantial performance hit, since the perl
interpreter will have to load, load up HTML::Mason and its supporting
modules for every CGI execution.  Using mod_perl or similar persistent
environments (SpeedyCGI, FastCGI, etc.) avoids this performance bottleneck.

=head2 What platforms does HTML::Mason run on?

We are aware of successful installations on Solaris, Linux, FreeBSD, HPUX
and Windows NT.

Because HTML::Mason consists of only Perl code (no C), it should work
anywhere Perl runs.  If it doesn't work on your operating system, let us
know.

=head2 Why am I getting 404 errors for pages that clearly exist?

The filename that Apache has resolved to may not fall underneath the
component root you specified when you created the interpreter in
handler.pl.  HTML::Mason requires the file to fall under the component
root so that it can call it as a top-level component.  (For various
reasons, such as object file creation, HTML::Mason cannot treat files
outside the component root as a component.)

If you believe the file is in fact inside the component root and HTML::Mason
is in error, it may be because you're referring to the Apache document root
or the HTML::Mason component root through a symbolic link.  The symbolic
link may confuse HTML::Mason into thinking that two directories are
different when they are in fact the same. This is a known "bug", but there
is no obvious fix at this time. For now, you must refrain from using
symbolic links in either of these configuration items.

=head2 How do I exit from all components including the ones that called me?

Use $m->abort, documented in the Request manual:

	http://www.masonhq.com/docs/manual/0.8/Request.html#item_abort_return_value_

=head2 How do I access GET or POST arguments?

GET and POST arguments are automatically parsed and placed into named
component arguments just as if you had called the component with <& &>
or $m->comp.  So you can get at GET/POST data by pre-declaring argument
names and/or using the %ARGS hash which is always available.

=head2 Should I use CGI.pm to read GET/POST arguments?

No! HTML::Mason automatically parses GET/POST arguments and places them in
declared component arguments and %ARGS (see previous question).  If you
create a CGI object in the usual way for a POST request, it will hang the
process trying to read $r->content a second time.

=head2 Can I use CGI.pm to output HTML constructs?

Yes. To get a new CGI object, use

	my $query = new CGI('');

You have to give the empty string argument or CGI will try to read GET/POST 
arguments.

To print HTML constructs returned by CGI functions, just enclose them in
<%%>, e.g.

	<% $query->radio_group(...) %>

=head2 How do I modify the outgoing HTTP headers?

Use the usual Apache.pm functions, such as $r->header_out.  See the
"Sending HTTP Headers" section in the Component Developer's Guide:

	http://www.masonhq.com/docs/manual/0.8/Devel.html#sending_http_headers

=head2 How do I do an external redirect?

Here's how to redirect to $url:

	<%init>
	# The next two lines are necessary to stop Apache from re-reading
	# POSTed data.
	$r->method('GET');
	$r->headers_in->unset('Content-length');

	$r->content_type('text/html');
	$r->header_out(Location=>$url);
	$m->abort(302);
	</%init>

=head2 Some of my pages are being served with content type xxx instead of text/html.  How do I get HTML::Mason to properly set the content type?

HTML::Mason doesn't actually touch the content type -- it relies on Apache
to set it correctly.  You can affect how Apache sets your content type in
the configuration files (e.g. srm.conf).  The most common change you'll want
to make is to add the line

	DefaultType text/html

This indicates that files with no extension and files with an unknown 
extension should be treated as text/html. By default, Apache would treat 
them as text/plain.

=head2 I have a line in my handler.pl to stop HTML::Mason from processing anything but text files, but I want to generate a dynamic image using HTML::Mason.  How can I get HTML::Mason to set the correct MIME type?

Use mod_perl's $r->content_type function to set the appropriate MIME type.
This will allow you to output, for example, a GIF file, even if your
component is called dynamicImage.html.

=head2 How do I put comments in components?

=over 4

=item *

Put general comments in the <%doc> section.

=item *

In the <%init> and <%cleanup> sections, and in a <%perl> block, 
use standard Perl comments ('#').

=item *

In the primary section, begin a line with %# to make it a comment

=item *

If you are producing HTML, you can use standard HTML comments delimited 
by <!-- -->.

=back

The difference between 3 and 4 is that %# comments will not appear in the 
output, while <!-- --> comments will appear. Both have their advantages.

=head2 What's a good way to temporarily comment out code in a component?

For HTML, you might be tempted to surround the section with <!-- -->.  But 
be careful! Any code inside the section will still execute. Here's a example 
of commenting out a call to an ad server:

	<!-- temporarily comment out
	<& FetchAd &>
	-->

The ad will still be fetched and counted, but not displayed!

A better way to block out a section is if (0):

	% if (0) {
		...
	% }

Code blocked out in this way will neither be executed nor displayed, and 
multiple if (0) blocks can be nested inside each other (unlike HTML comments).

=head2 How can I capture the output of a component (and modify it, etc.) instead of having it automatically output?

Use $m->scomp, documented in the Request manual:

	http://www.masonhq.com/docs/manual/0.8/Request.html#item_scomp

=head2 Can I use globals in components?

All HTML::Mason components run in the same package (HTML::Mason::Commands),
so if you set a global variable in one you'll be able to read it in all the
others. You can also initialize global variables in the handler() subroutine
in handler.pl as long as you explicitly put them in the
HTML::Mason::Commands package.

The only problem is that Mason by default parses components with strict mode
on, so you'll get a warning about the global (and Mason considers all such
warnings fatal). To get around this you need to declare the global in a
"use vars" statement inside the HTML::Mason::Commands package:

	package HTML::Mason::Commands;
	use vars qw(...);

or use the Parser allow_globals parameter.  See the section on globals in
the Administrator's Guide:

	http://www.masonhq.com/docs/manual/Admin.html#using_global_variables

Alternatively you can turn off strict entirely by passing:

	use_strict => 0

when you create the Parser object.  Then you can use all the globals you 
want.  Doing this is terribly silly, however, and is bound to get you in
trouble down the road.

=head2 Can Mason support multiple component roots, with searching, ala Perl's @INC?

As of Mason 0.8, yes!  Consult the "Component roots (multiple)" section in the
Administrator's Guide:

	http://www.masonhq.com/docs/manual/0.8/Admin.html#component_roots_multiple_

=head2 Do data cache files expire automatically when a component or its dependencies change?

Eventually, but not right now. Unfortunately, it is difficult for Mason to 
check this efficiently in the current implementation.  But you can use the 
following idiom to say "expire when my component source file changes":

	$m->cache(..., expire_if=>sub { (stat($m->source_file))[9] > $_[0] } )

=head2 Why does the order of output get mixed up when I use print or $r->print?

Since your server is most likely in batch mode, all Mason output gets
buffered til the end of the request.  print and $r->print circumvent
the buffer and thus come out before other Mason output.

Solution: don't use print or $r->print. Use $m->out if you must output
inside a Perl section. See the section on output mode in the
Administrator's Guide:

	http://www.masonhq.com/docs/manual/Admin.html#out_mode

and the section on $m->out in the Request manual:

	http://www.masonhq.com/docs/manual/Request.html#item_out_string

=head2 How can I handle file uploads under Mason?

The way you handle this depends on which args method you chose for the
ApacheHandler class.

Under the default method, 'CGI', which uses the CGI.pm module to
handle incoming arguments, you can use the $m->cgi_object method to
retrieve a CGI.pm object which can be used to retrieve the uploaded
file(s).  Please see the CGI.pm documentation for more details.

If you are using the 'mod_perl' method, which uses Apache::Request,
then the request object available in your components will be an object
in the Apache::Request class (as opposed to the Apache class).  This
object is capable of returning Apache::Upload objects for parameters
which were file uploads.  Please see the Apache::Request documentation
for more details.

=cut
