The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Apache::ErrorControl - Apache Handler for Templating Apache Error Documents

SYNOPSIS

in your httpd.conf

  PerlModule Apache::ErrorControl

  <Location /error>
    SetHandler perl-script
    PerlHandler Apache::ErrorControl

    PerlSetVar TemplateDir /usr/local/apache/templates
  </Location>

  ErrorDocument 400 /error
  ErrorDocument 401 /error
  ErrorDocument 402 /error
  ErrorDocument 403 /error
  ErrorDocument 404 /error
  ErrorDocument 500 /error

in your template (allerrors.tmpl):

  <TMPL_SET NAME="webmaster_email">dj@boxen.net</TMPL_SET>

  <HTML>
    <HEAD>
      <TITLE>Error <TMPL_VAR NAME="error_code"></TITLE>
    </HEAD>

    <BODY>
      <TMPL_IF NAME="404">
        <H1>Error 404: File Not Found</H1>
        <HR><BR>

        <p>The file you were looking for is not here, we must have
          deleted it - or you just might be mentally retarded</p>
      </TMPL_IF>
      <TMPL_IF NAME="500">
        <H1>Error 500: Internal Server Error</H1>
        <HR><BR>

        <p>We are currently experiencing problems with our server,
          please call back later</p>
      </TMPL_IF>

      <p><b>Time of Error:</b> <TMPL_VAR NAME="date"></p>
      <p><b>Requested From:</b> <TMPL_VAR NAME="requestor"></p>
      <p><b>Requested URL:</b> <TMPL_VAR NAME="request_url"></p>
      <p><b>Website Base URL:</b> <TMPL_VAR NAME="base_url"></p>
      <p><b>Contact Email:</b> support@mouse.com</p>
    </BODY>
  </HTML>

DESCRIPTION

This mod_perl content handler will make templating your ErrorDocument pages easy. Basically you add a couple of entries to your httpd.conf file restart apache, make your template and your cruising.

The module uses 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: HTML::Template::Set and HTML::Template. Also check the 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 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 EmailOn option for how to do this.

Templates are looked up in the following order: the document root is scanned for 'allerrors', 'allerrors.tmpl', error code or error code.tmpl. if no templates are found the TemplateDir is scanned for the same files. if no templates are found the DefaultTemplate is used and if its not set the system 'dies'.

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.

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.

TESTING

Obviously you will need the ability to test your templates, and trying to generate each error code would be a pain in the ass. So to counter this I have implemented a testing/static mode. Basically you call the handler with "/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 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 error code, unless of course you run into problems for some reason and are forced to.

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 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.

  • headers_in.txt - the inwards headers, a snapshot of the Apache::Table retrieved from $r->prev()->headers_in().

  • headers_out.txt - the outwards headers, a snapshot of the Apache::Table retrieved from $r->prev()->headers_out().

  • err_headers_out.txt - the outwards error headers, a snapshot of the Apache::Table retrieved from $r->prev()->err_headers_out().

  • subprocess_env.txt - the sub process environment, a snapshot of the Apache::Table retrieved from $r->prev()->subprocess_env().

  • env.txt - a snapshot of the ENV (global environment variables) hash.

  • post_data.txt - the POST data, a snapshot of the hash from $r->prev()->content(). this is the only way I know of retrieving the POST data and it will *ONLY* be present during 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 POST data for a different error code. GET data of course is tacked onto the end of the request_uri. the POST data will also not appear unless the Content-Type is application/x-www-form-urlencoded.

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

OPTIONS

HTTPD CONFIG

  • 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 error code, error code.tmpl, allerrors, allerrors.tmpl - then falling back to looking for the files mentioned before under the document root - then falling back to using the DefaultTemplate - then 'dieing'). the TemplateDir is also passed to HTML::Template::Set as the path option.

      PerlSetVar TemplateDir "/usr/local/apache/templates"
  • DefaultTemplate - the default template file to use, can be just a filename (to be looked up under TemplateDir) or the full path to the file.

      PerlSetVar DefaultTemplate "myerrors.tmpl"
  • 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. -t for sendmail).

      PerlSetVar MTA "/usr/lib/sendmail -t"
  • DateFormat - you can specify the date format to use in emails and in the templates here. just provide a strftime format. this can be overrided on a per template basis with the date_format TMPL_SET param. if this isnt specified a default date format is used.

      PerlSetVar DateFormat "%Y-%m-%d %H:%M:%S"
  • 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"
  • EmailServerAdmin - if you want the server admin to receive a copy of the email please turn this option on (set it to 1). this is more useful in a virtual hosting environment where the server admin is different for each virtual host.

      PerlSetVar EmailServerAdmin 1

    DisableEmail - if you want to disable error emails all together then set this to true. this is a good way of disabling emails during fixing a problem (rather than removing all the email settings, directive by directive, template by template).

      PerlSetVar DisableEmail 1
  • EmailOn - if you want to recieve emails for more than just internal server errors (500) then specify an EmailOn for each using a PerlAddVar instead of a PerlSetVar.

      PerlAddVar EmailOn 403
      PerlAddVar EmailOn 500

TEMPLATE

TMPL_SET

  • webmaster_email - this paramater allows you to set add an email address to send error messages to on a per-template basis.

      <TMPL_SET NAME="webmaster_email">dj@abc.com</TMPL_SET>
  • date_format - this option overrides the DateFormat HTTPD CONF entry on a per-template basis.

      <TMPL_SET NAME="date_format">%d-%m-%Y %H:%M:S</TMPL_SET>

TMPL_VAR / TMPL_IF

  • requestor - the requestor of the page either "user (hostname (ip))", "user (ip)", "hostname (ip)" or "ip", depending if their ip resolves or not. NB: unless you have "HostnameLookups On" in you httpd.conf you will never see the users hostname.

      <TMPL_VAR NAME="requestor">
  • base_url - the base url of the website, i.e. http://www.abc.com

      <TMPL_VAR NAME="base_url">
  • request_url - the full request url including arguments, i.e. http://www.abc.com/stuff/stuffed.cgi?abc=yes&no=yes

      <TMPL_VAR NAME="request_url">
  • date - the date/time of the error (format depending on the DateFormat / date_format.

      <TMPL_VAR NAME="date">
  • error_code - the error code, i.e. 404, 403, 500 etc

      <TMPL_VAR NAME="error_code">
  • *error_code* - the actual error code itself is set as a param (if the param exists). if there is no TMPL_IF or TMPL_VAR defined for the error code encountered the param unknown_error is turned on (obviously only if it too is defined). personally I cant see why anyone would ever need unknown_error but ive added it here anyways.

      <TMPL_IF NAME="404">
        Error 404 - File Not Found
      </TMPL_IF>
  • unknown_error - if the *error_code* is not defined as a TMPL_VAR or TMPL_IF and there is a TMPL_IF / TMPL_VAR by the name of unknown_error it is set to TRUE (1). as mentioned above I cannot see why anyone would want this.

      <TMPL_IF NAME="unknown_error">
        Error <TMPL_VAR NAME="error_code"> - Unknown
      </TMPL_IF>
  • error_notes - the error-notes ($r->prev()->notes('error-notes'), see Apache). this is more useful in say a staging environment that has mod_perl applications. it is the error message, for mod_perl applications it includes the complete error message but for normal cgi applications it just includes 'premature end of script headers'.

      <TMPL_IF NAME="error_notes">
        <h2>Error Notes</h2>
        <pre>
        <TMPL_VAR NAME="error_notes">
        </pre>
      </TMPL_IF>
  • env_* - all env_* params are available, see HTML::Template::Set for details.

      <TMPL_VAR NAME="env_server_name">

OPTIMISATION

As the module loads HTML::Template::Set with the cache option all templates are automatically cached. To further increase the performance you should look at the documentation of HTML::Template for instructions on how to pre-load your templates under mod_perl. If you do not use this methodology HTML::Template will only cache your templates per apache child process and upon using them (i.e. before you will notice the benefits of using cache each apache child process needs to load each template).

CAVEATS

This module may be missing something that you feel it needs, it has everything I have wanted though. If you want a feature added please email me or send me a patch.

One thing to note is that if you go to your handler directly (i.e. http://www.abc.com/error) the system will return FORBIDDEN. this will also happen if your error code is ever 200 (OK) (which it should never be unless you are accessing the handler directly). If you are interested in testing your templates see the TESTING section.

BUGS

I am aware of no bugs - if you find one, just drop me an email and i'll try and nut it out (or email a patch, that would be tops!).

SEE ALSO

HTML::Template::Set, HTML::Template, Apache

AUTHOR

David J Radunz <dj@boxen.net>

LICENSE

Apache::ErrorControl : Apache Handler for Templating Apache Error Documents

Copyright (C) 2004 David J Radunz (dj@boxen.net)

This module is free software; you can redistribute it and/or modify it under the terms of either:

a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or

b) the "Artistic License" which comes with this module.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the Artistic License for more details.

You should have received a copy of the Artistic License with this module, in the file ARTISTIC. If not, I'll be glad to provide one.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA