block. If an error occurs, we store it in the request
object using the C<< $r->pnotes() >> method. Then we change the
filename property of the Apache request object to point to our
error-handling component and call the C<< $ah->handle_request() >>
method again, passing it the altered request object. We could have
put the exception in C<< $r->args >>, but we want to leave this
untouched so that the error-handling component can see the original
arguments.
Here's what that component error-handling component might look like:
Error
Looks like our application broke. Whatever you did, don't do it again!
If you have further questions, please feel free to contact us at support@example.com.
Click here to continue.
<%init>
my $error = $r->pnotes('error');
my $error_text = "Page is " . $r->parsed_uri->unparse . "\n\n";
$error_text .= UNIVERSAL::can( $error, 'as_text' ) ? $error->as_text : $error;
$r->log_error($error_text);
my $mail =
MIME::Lite->new
( From => 'error-handler@example.com',
To => 'rt@example.com',
Subject => 'Application error',
Data => $error_text,
);
$r->register_cleanup( sub { $mail->send } );
%init>
<%flags>
inherit => undef
%flags>
This component does several things. First of all, it logs the
complete error to the Apache error logs, along with the complete URL,
including query string, that was requested. The C<< $r->parsed_uri() >>
method that we use above is only available if the C
module has been loaded.
The component also sends an email containing the error, in this case
to an RT installation, so that the error is logged in a bug tracking
system. Finally, it displays a less technical error message to the
user.
For this to work properly, you must set L to "fatal", so
that Mason doesn't just display its own HTML error page.
=head1 RUNNING OUTSIDE OF MOD_PERL
Although Mason is most commonly used in conjunction with mod_perl, the
APIs are flexible enough to use in any environment. Below we describe
the two most common alternative environments, CGI and standalone
scripts.
=head2 Using Mason from a CGI Script
The easiest way to use Mason via a CGI script is with the L module.
Here is a skeleton CGI script that calls a component and sends the
output to the browser.
#!/usr/bin/perl
use HTML::Mason::CGIHandler;
my $h = HTML::Mason::CGIHandler->new
(
data_dir => '/home/jethro/code/mason_data',
);
$h->handle_request;
The relevant portions of the F file look like:
DocumentRoot /path/to/comp/root
ScriptAlias /cgi-bin/ /path/to/cgi-bin/
Action html-mason /cgi-bin/mason_handler.cgi
AddHandler html-mason .html
RemoveHandler .html
Order allow,deny
Deny from all
This simply causes Apache to call the mason_handler.cgi script every
time a URL ending in ".html" under the component root is requested.
To exclude certain directories from being under Mason control, you can
use something like the following:
RemoveHandler .html
This script uses the L to do
most of the heavy lifting. See that class's documentation for more
details.
=head2 Using Mason from a Standalone Script
Mason can be used as a pure text templating solution -- like
Text::Template and its brethren, but with more power (and of course
more complexity).
Here is a bare-bones script that calls a component file and sends
the result to standard output:
#!/usr/bin/perl
use HTML::Mason;
use strict;
my $interp = HTML::Mason::Interp->new ();
$interp->exec(, ...);
Because no component root was specified, the root is set to your
current working directory. If you have a well defined and contained
component tree, you'll probably want to specify a component root.
Because no data directory was specified, object files will not be
created and data caching will not work in the default manner. If
performance is an issue, you will want to specify a data directory.
Here's a slightly fuller script that specifies a component root and
data directory, and captures the result in a variable rather than
sending to standard output:
#!/usr/bin/perl
use HTML::Mason;
use strict;
my $outbuf;
my $interp = HTML::Mason::Interp->new
(comp_root => '/path/to/comp_root',
data_dir => '/path/to/data_dir',
out_method => \$outbuf
);
$interp->exec(, ...);
# Do something with $outbuf
=cut