With the mod_perl stacked handlers mechanism, it is possible for more than one Perl*Handler to be defined and executed during any stage of a request.

Perl*Handler directives can define any number of subroutines. For example:

PerlTransHandler Foo::foo Bar::bar

Foo::foo( ) will be executed first and Bar::bar( )second. As always, if the subroutine's name is handler( ), you can omit it.

With the Apache->push_handlers( ) method, callbacks (handlers) can be added to a stack at runtime by mod_perl modules.

Apache->push_handlers( ) takes the callback handler name as its first argument and a subroutine name or reference as its second. For example, let's add two handlers called my_logger1( ) and my_logger2( ) to be executed during the logging phase:

use Apache::Constants qw(:common);
sub my_logger1 {
    #some code here
    return OK;
}
sub my_logger2 {
    #some other code here
    return OK;
}
Apache->push_handlers("PerlLogHandler", \&my_logger1);
Apache->push_handlers("PerlLogHandler", \&my_logger2);

You can also pass a reference to an anonymous subroutine. For example:

use Apache::Constants qw(:common);

Apache->push_handlers("PerlLogHandler", sub {
    print STDERR "_ _ANON_ _ called\n";
    return OK;
});

After each request, this stack is erased.

All handlers will be called in turn, unless a handler returns a status other than OK or DECLINED.

To enable this feature, build mod_perl with:

panic% perl Makefile.PL PERL_STACKED_HANDLERS=1 [ ... ]

or:

panic% perl Makefile.PL EVERYTHING=1 [ ... ]

To test whether the version of mod_perl you're running can stack handlers, use the Apache->can_stack_handlers method. This method will return a true value if mod_perl was configured with PERL_STACKED_HANDLERS=1, and a false value otherwise.

Let's look at a few real-world examples where this method is used:

Now let's write our own example using stacked handlers. Imagine that you want to piece together a document that includes footers, headers, etc. without using SSI. The following example shows how to implement it. First we prepare the code as shown in Example 4-1.

Example 4-1. Book/Compose.pm

package Book::Compose;
use Apache::Constants qw(OK);

sub header {
    my $r = shift;
    $r->send_http_header("text/plain");
    $r->print("header text\n");
    return OK;
}
sub body   {
    shift->print("body text\n");
    return OK;
}
sub footer {
    shift->print("footer text\n");
    return OK;
}
1;

The code defines the package Book::Compose, imports the OK constant, and defines three subroutines: header( ) to send the header, body( ) to create and send the actual content, and finally footer( ) to add a standard footer to the page. At the end of each handler we return OK, so the next handler, if any, will be executed.

To enable the construction of the page, we now supply the following configuration:

PerlModule Book::Compose
<Location /compose>
    SetHandler perl-script
    PerlHandler Book::Compose::header Book::Compose::body Book::Compose::footer
 </Location>

We preload the Book::Compose module and construct the PerlHandler directive by listing the handlers in the order in which they should be invoked.[25]

[25]It may not seem to make sense to use this example, as it would be much simpler to write a single handler to call all three subroutines. But what if the three reside in different modules that are maintained by different authors?

Finally, let's look at the technique that allows parsing the output of another PerlHandler. For example, suppose your module generates HTML responses, but you want the same content to be delivered in plain text at a different location. This is a little trickier, but consider the following:

<Location /perl>
    SetHandler perl-script
    PerlHandler Book::HTMLContentGenerator
</Location>
<Location /text>
    SetHandler perl-script
    PerlHandler Book::HTML2TextConvertor Book::HTMLContentGenerator
</Location>

Notice that Book::HTML2TextConvertor is listed first. While its handler( ) will be called first, the actual code that does the conversion will run last, as we will explain in a moment. Now let's look at the sample code in Example 4-2.

Example 4-2. Book/HTML2TextConvertor.pm

package Book::HTML2TextConvertor;

sub handler {
    my $r = shift;
    untie *STDOUT;
    tie *STDOUT => _ _PACKAGE_ _, $r;
}

sub TIEHANDLE {
    my($class, $r) = @_;
    bless { r => $r}, $class;
}

sub PRINT {
    my $self = shift;
    for (@_) {
        # copy it so no 'read-only value modification' will happen
        my $line = $_;
        $line =~ s/<[^>]*>//g; # strip the html <tags>
        $self->{r}->print($line);
    }
}

1;

It untie( )s STDOUT and re-tie( )s it to its own package, so that content printed to STDOUT by the previous content generator in the pipe goes through this module. In the PRINT( ) method, we attempt to strip the HTML tags. Of course, this is only an example; correct HTML stripping actually requires more than one line of code and a quite complex regular expression, but you get the idea.