Apache-ErrorControl
view release on metacpan or search on metacpan
ErrorControl.pm view on Meta::CPAN
if ($c->user()) {
$requestor = $c->user(). ' ('. $requestor. ')';
}
if (exists $params{requestor}) {
$tmpl->param( requestor => $requestor );
}
# build the 'base_url' TMPL_VAR (made up from the server_name etc)
my $base_url;
if (exists $ENV{'HTTPS'} and $ENV{'HTTPS'}) {
$base_url = 'https://';
} else {
$base_url = 'http://';
}
$base_url .= $s->server_hostname();
if (exists $params{base_url}) {
$tmpl->param( base_url => $base_url );
}
# build the 'request_url' TMPL_VAR (made up from the base_urlm
# the url and the args)
my $request_url = $base_url;
if ($r->prev()) {
$request_url .= $r->prev()->uri();
if ($r->prev()->args()) {
$request_url .= '?'. $r->prev()->args();
}
} else {
$request_url .= $r->uri();
if ($r->args()) {
$request_url .= '?'. $r->args();
}
}
if (exists $params{request_url}) {
$tmpl->param( request_url => $request_url );
}
# }}}
# Send Email For Internal Server Error {{{
if (@email > 0) {
# build our email
my $mobj = MIME::Entity->build(
'From' => 'Apache::ErrorControl <apache-errorcontrol@'.
$s->server_hostname(). '>',
'Subject' => 'Error '. $self->{error_code}. ' on '.
$s->server_hostname(),
'Type' => 'multipart/mixed',
'X-Mailer' => 'Apache::ErrorControl'
);
my $body = 'Time: '. $formatted_date. "\n".
'Requested URL: '. $request_url. "\n".
'Requested By: '. $requestor. "\n\n".
"--------------------\n".
"Apache::ErrorControl\n\n";
$mobj->attach(
Data => $body,
Type => 'text/plain'
);
# Construct Included Debug
my %content;
my ($headers_in, $headers_out, $err_headers_out, $subprocess_env);
if ($r->prev()) {
%content = $r->prev()->content();
$headers_in = $r->prev()->headers_in();
$headers_out = $r->prev()->headers_out();
$err_headers_out = $r->prev()->err_headers_out();
$subprocess_env = $r->prev()->subprocess_env();
}
# NB: retrieval of POST data will only work on status 204, 304, 400, 408,
# 411, 413, 414, 500, 501, 503 - hey one of them is 500 so im happy :D :D
my %files = (
headers_in => $headers_in,
headers_out => $headers_out,
err_headers_out => $err_headers_out,
notes => $notes,
subprocess_env => $subprocess_env,
post_data => \%content,
env => \%ENV
);
foreach my $file (keys %files) {
my $string = $self->apache_table_to_string($files{$file});
if ($string) {
$mobj->attach(
Data => $string,
Filename => $file. '.txt',
Type => 'text/plain',
Encoding => 'base64'
);
}
}
foreach my $email_address (@email) {
$mobj->head()->replace('To', $email_address);
open(MTAHANDLE,"|$MTA_Prog")
or die "Failed to open MTA: ". $MTA_Prog. ": $!\n";
$mobj->print(\*MTAHANDLE);
close(MTAHANDLE);
}
}
# }}}
# Send Headers {{{
$r->content_type('text/html; charset=ISO-8859-1');
$r->send_http_header;
# }}}
# Send Template {{{
$r->print($tmpl->output());
# }}}
return;
}
# }}}
# Apache Table To String Function {{{
sub apache_table_to_string {
my ($self, $table) = @_;
return unless ($table);
my @string = ();
while(my($key,$val) = each %$table) {
next unless ($key);
my $string = sprintf("%-15s", $key);
$string .= $val if ($val);
push(@string, $string);
}
return join("\n", @string);
}
# }}}
# Find Error Template Function {{{
# im not sure why I chose to allow so many paths/filenames but I think its
# better to be flexiable.
sub find_error_template {
my ($self) = @_;
ErrorControl.pm view on Meta::CPAN
easy. Basically you add a couple of entries to your httpd.conf file restart
apache, make your template and your cruising.
The module uses L<HTML::Template::Set> (which is essentially HTML::Template
with the ability to use TMPL_SET tags). So for help templating your error
pages please see: L<HTML::Template::Set> and L<HTML::Template>. Also check
the B<OPTIONS> section of this documentation for available TMPL_SET/TMPL_IF
and TMPL_VAR params.
By default when an error 500 (internal server error) is encountered an error
email is sent about it. the addresses emailed depend on the options specified.
please see the B<OPTIONS> section for help configuring this. you can also
extend the system to send error emails on more than just internal server
errors, please see the B<EmailOn> option for how to do this.
Templates are looked up in the following order: the I<document root> is scanned
for 'allerrors', 'allerrors.tmpl', I<error code> or I<error code>.tmpl. if
no templates are found the B<TemplateDir> is scanned for the same files. if
no templates are found the B<DefaultTemplate> is used and if its not set
the system 'B<die>s'.
Because so many places are checked for the templates its possible to have
one global error handler and have different templates for each virtual host
and also allow for defaults. It also means you can have a general catch-all
template (allerrors/allerrors.tmpl) as well as single templates (i.e. 500.tmpl).
Generally I just use allerrors.tmpl and use TMPL_IF's to display custom content
per error message, but you can set it up any way you want.
=head1 MOTIVATION
I wanted to write a mod_perl handler so I could template error messages.
I also wanted to make it extensible enough that I could have a global error
handler and it would cover all the virtual webservers and have different
templates for each of them - ergo - the birth of Apache::ErrorControl.
=head1 TESTING
Obviously you will need the ability to test your templates, and trying to
generate each I<error code> would be a pain in the ass. So to counter this
I have implemented a B<testing>/B<static> mode. Basically you call the handler
with "/I<error code>" tacked on the end. You can also use this to define static
error pages if you dont want the system to "automagically" determine the
I<error code>.
to test error 401:
http://www.abc.com/error/401
to statically configure error 401:
ErrorDocument 401 /error/401
I dont see why you would want to statically configure an I<error code>, unless
of course you run into problems for some reason and are forced to.
=head1 ERROR EMAILS
This module has the ability to send an email on an error. you can define
what error code to email on and what email addresses to send emails to, please
see the B<OPTIONS> section on how to do this. the error email contains various
attached files and these are present in the email depending on weather or not
their data could be retrieved. the attached files are detailed below.
=over 4
=item *
B<headers_in.txt> - the inwards headers, a snapshot of the L<Apache::Table>
retrieved from C<$r-E<gt>prev()-E<gt>headers_in()>.
=item *
B<headers_out.txt> - the outwards headers, a snapshot of the L<Apache::Table>
retrieved from C<$r-E<gt>prev()-E<gt>headers_out()>.
=item *
B<err_headers_out.txt> - the outwards error headers, a snapshot of the
L<Apache::Table> retrieved from C<$r-E<gt>prev()-E<gt>err_headers_out()>.
=item *
B<subprocess_env.txt> - the sub process environment, a snapshot of the
L<Apache::Table> retrieved from C<$r-E<gt>prev()-E<gt>subprocess_env()>.
=item *
B<env.txt> - a snapshot of the ENV (global environment variables) hash.
=item *
B<post_data.txt> - the I<POST> data, a snapshot of the
hash from C<$r-E<gt>prev()-E<gt>content()>. this is the only way I know of
retrieving the I<POST> data and it will B<*ONLY*> be present during
I<error codes>: 204, 304, 400, 408, 411, 413, 414, 500, 501, 503 which doesnt
worry me since 500 is one of the mentioned codes - but you may need the
I<POST> data for a different I<error code>. I<GET> data of course is tacked
onto the end of the request_uri. the I<POST> data will also not appear
unless the I<Content-Type> is C<application/x-www-form-urlencoded>.
=back
=head2 EXAMPLE EMAIL
Below is an example email (obviously missing the file attachments).
Subject: Error 500 on www.abc.com
Time: 2004-05-05 14:27:22
Requested URL: http://www.abc.com/testing/testing123.cgi
Requested By: dj (dj.abc.com (10.0.0.10))
--------------------
Apache::ErrorControl
=head1 OPTIONS
=head2 HTTPD CONFIG
=over 4
=item *
B<TemplateDir> - the directory of your templates, this path will be used
when looking up the template for the error message (looking in it for either
I<error code>, I<error code>.tmpl, allerrors, allerrors.tmpl - then falling back
to looking for the files mentioned before under the I<document root> - then
falling back to using the B<DefaultTemplate> - then 'B<die>ing').
the B<TemplateDir> is also passed to L<HTML::Template::Set> as the B<path>
option.
PerlSetVar TemplateDir "/usr/local/apache/templates"
=item *
B<DefaultTemplate> - the default template file to use, can be just a filename
(to be looked up under B<TemplateDir>) or the full path to the file.
PerlSetVar DefaultTemplate "myerrors.tmpl"
=item *
B<MTA> - (Mail Transport Agent), basically the path to the program to send
email with (i.e. sendmail, qmail-send etc). dont forget to provide any options
needed for your MTA to function correctly (i.e. B<-t> for sendmail).
PerlSetVar MTA "/usr/lib/sendmail -t"
=item *
B<DateFormat> - you can specify the date format to use in emails and in the
templates here. just provide a B<strftime> format. this can be overrided on a
per template basis with the B<date_format> TMPL_SET param. if this isnt
specified a default date format is used.
PerlSetVar DateFormat "%Y-%m-%d %H:%M:%S"
=item *
B<EmailTo> - to specify globally email addresses to send messages to please
use this option. use a PerlAddVar for each email you wish to send to.
PerlAddVar EmailTo "dj@abc.com.au"
PerlAddVar EmailTo "dj@xyz.com.au"
( run in 1.369 second using v1.01-cache-2.11-cpan-e1769b4cff6 )