4.2.4. Perl*Handlers
As mentioned in Chapter 1, Apache specifies 11 phases of
the request loop. In order of processing,
they are: Post-read-request, URI
translation, header parsing,
access control,
authentication,
authorization, MIME type
checking, fixup,
response (also known as the content handling
phase), logging, and finally
cleanup. These are the stages of a request where
the Apache API allows a module to step in and do something. mod_perl
provides dedicated configuration directives for each of these stages:
PerlPostReadRequestHandler
PerlInitHandler
PerlTransHandler
PerlHeaderParserHandler
PerlAccessHandler
PerlAuthenHandler
PerlAuthzHandler
PerlTypeHandler
PerlFixupHandler
PerlHandler
PerlLogHandler
PerlCleanupHandler
These configuration directives usually are referred to as
Perl*Handler directives. The *
in Perl*Handler is a placeholder to be replaced by
something that identifies the phase to be handled. For example,
PerlLogHandler is the Perl handler that (fairly
obviously) handles the logging phase.
In addition, mod_perl adds a few more stages that happen outside the
request loop:
- PerlChildInitHandler
-
Allows your modules to initialize data structures during the startup
of the child process.
- PerlChildExitHandler
-
Allows your modules to clean up during the child process shutdown.
PerlChildInitHandler and
PerlChildExitHandler might be used, for example,
to allocate and deallocate system resources, pre-open and close
database connections, etc. They do not refer to parts of the request
loop.
- PerlRestartHandler
-
Allows you to specify a routine that is called when the server is
restarted. Since Apache always restarts itself immediately after it
starts, this is a good phase for doing various initializations just
before the child processes are spawned.
- PerlDispatchHandler
-
Can be used to take over the process of loading and executing handler
code. Instead of processing the Perl*Handler
directives directly, mod_perl will invoke the routine pointed to by
PerlDispatchHandler and pass it the Apache request
object and a second argument indicating the handler that would
ordinarily be invoked to process this phase. So for example, you can
write a PerlDispatchHandler handler with a logic
that will allow only specific code to be executed.
Since most mod_perl applications need to handle only the response
phase, in the default compilation, most of the
Perl*Handlers are disabled. During the
perl Makefile.PL mod_perl build stage, you must
specify whether or not you will want to handle parts of the request
loop other than the usual content generation phase. If this is the
case, you need to specify which phases, or build mod_perl with the
option EVERYTHING=1, which enables them all. All
the build options are covered in detail in Chapter 3.
Note that it is mod_perl that recognizes these directives, not
Apache. They are mod_perl directives, and an ordinary Apache server
will not recognize them. If you get error messages about these
directives being "perhaps
mis-spelled," it is a sure sign that the appropriate
part of mod_perl (or the entire mod_perl module!) is missing from
your server.
All <Location>,
<Directory>, and
<Files>sections contain a physical path
specification. Like PerlChildInitHandler and
PerlChildExitHandler, the directives
PerlPostReadRequestHandler and
PerlTransHandler cannot be used in these sections,
nor in .htaccess files, because the path
translation isn't completed and a physical path
isn't known until the end of the translation
(PerlTransHandler) phase.
PerlInitHandler is more of an alias; its behavior
changes depending on where it is used. In any case, it is the first
handler to be invoked when serving a request. If found outside any
<Location>,
<Directory>, or
<Files>section, it is an alias for
PerlPostReadRequestHandler. When inside any such
section, it is an alias for
PerlHeaderParserHandler.
Starting with the header parsing phase, the
requested URI has been mapped to a physical server pathname, and thus
PerlHeaderParserHandler can be used to match a
<Location>,
<Directory>, or
<Files> configuration section, or to process
an .htaccess file if such a file exists in the
specified directory in the translated path.
PerlDispatchHandler,
PerlCleanupHandler, and
PerlRestartHandler do not correspond to parts of
the Apache API, but allow you to fine-tune the mod_perl API. They are
specified outside configuration sections.
The Apache documentation and the book Writing Apache
Modules with Perl and C (O'Reilly)
provide in-depth information on the request phases.
4.2.10. PerlSetEnv and PerlPassEnv
In addition to Apache's
SetEnv and PassEnv directives,
respectively setting and passing shell environment variables,
mod_perl provides its own directives:
PerlSetEnv and
PerlPassEnv.
If you want to globally set an environment variable for the server,
you can use the PerlSetEnv directive. For example,
to configure the mod_perl tracing mechanism (as discussed in Chapter 21), add this to httpd.conf:
PerlSetEnv MOD_PERL_TRACE all
This will enable full mod_perl tracing.
Normally, PATH is the only shell environment
variable available under mod_perl. If you need to rely on other
environment variables, you can have mod_perl make those available for
your code with PerlPassEnv.
For example, to forward the environment variable
HOME (which is usually set to the home of the user
who has invoked the server in httpd.conf), add:
PerlPassEnv HOME
Once you set the environment variable, it can be accessed via the
%ENV hash in Perl (e.g.,
$ENV{HOME}).
PerlSetEnv and PerlPassEnv work
just like the Apache equivalents, except that they take effect in the
first phase of the Apache request cycle. The standard Apache
directives SetEnv and PassEnv
don't affect the environment until the fixup phase,
which happens much later, just before content generation. This works
for CGI scripts, which aren't run before then, but
if you need to set some environment variables and access them in a
handler invoked before the response stage, you should use the
mod_perl directives. For example, handlers that want to use an Oracle
relational database during the authentication phase might need to set
the following environment variable (among others) in
httpd.conf:
PerlSetEnv ORACLE_HOME /share/lib/oracle/
Note that PerlSetEnv will override the environment
variables that were available earlier. For example, we have mentioned
that PATH is always supplied by Apache itself. But
if you explicitly set:
PerlSetEnv PATH /tmp
this setting will be used instead of the one set in the shell program.
As with other configuration scoping rules, if you place
PerlSetEnv or PerlPassEnv in
the scope of the configuration file, it will apply everywhere (unless
overridden). If placed into a <Location>
section, or another section in the same group, these directives will
influence only the handlers in that section.