Say we want to append a small chunk of content to each document, like those
banners and pop-ups that many free Web hosting companies use. In this
example, we'll drop in some text after the BODY tag.
First let's tell Apache to attach our text to every HTML file. In your
"access.conf" file, add something like this:
. Be careful,
since that can cause things to break if you're using frames.
To complete the request, mod_perl needs to reference this module:
package Apache::Add_Header;
use Apache ();
sub handler {
my $r = shift; # @_[0] contains a reference to
# the current request handler
my ($file) = $r->filename; # Full pathname to file
if (open(FILE,$file)) {
my ($body_start) = 0;
$r->send_http_header;
$r->status(200);
while (<FILE>) {
my ($line) = $_;
if ($line =~ /([^>]*<)([^ >]+)([^>]+>)(.*)/) {
my ($before_tag) = $1;
my ($tag_identifier) = $2;
my ($rest_of_tag) = $3;
my ($rest_of_line) = $4;
if ($tag_identifier =~ /body/i) {
# Complete body tag was found.
$r->print($before_tag);
$r->print($tag_identifier);
$r->print($rest_of_tag);
&message($r);
$r->print($rest_of_line);
} else {
$r->print($line);
}
} elsif ($line =~ /([^>]*<)([^ >]+)([^>]+)/) {
my ($before_tag) = $1;
my ($tag_identifier) = $2;
my ($rest_of_tag) = $3;
if ($tag_identifier =~ /body/i) {
# got a body tag that wraps multiple
# lines
$body_start=1;
}
$r->print($line);
} elsif (($body_start == 1) &&
($line =~ /([^>]*>)(.*)/)) {
my ($rest_of_tag) = $1;
my ($rest_of_line) = $2;
$r->print($rest_of_tag);
&message($r);
$r->print($rest_of_line);
$body_start=0;
} else {
$r->print($line);
}
}
} else {
$r->send_http_header;
$r->status(403);
}
return $r->status;
}
sub message {
my ($r) = shift;
$r->print("<center>Thanks for using this service!</center><p>\n");
}
1;
Give this module the filename Add_Header.pm, and save it in the Apache
directory in Perl's search path. If you're running Unix, this directory is
usually /usr/lib/perl5/site_perl/Apache.
Let's take a look at how this script is interacting with Apache. The
first line - package Apache::Add_Header; - must correspond to the
correct location in the
file system. If the file name and the package name don't match,
Perl won't compile the script properly. Next, import the routines
that tell it how
to interact with Apache. This module is named Apache.pm, and it's part
of the mod_perl installation. It ties your input and output to Apache,
and it also
gives you information about the current connection. To learn more about
this module, check out the documentation, accessible by running perldoc
Apache from the command line.
Each request then calls the handler subroutine, which passes a
reference to the request object. This object contains all the information
and routines necessary to build and service a request. In this example,
the first thing we needed to do was send a status header to the client. Note that you must use the interface provided by
Apache.pm to send information to the client. You can't simply use the print statement provided by Perl because the
STDIN
and STDOUT streams aren't tied to your script like they are with a CGI
script. To send text to the
client, we use the print function in the request object,
$r->print("text").
Lastly, remember to return a status code to Apache. Note that it is
possible to return a different status code to the client than the one sent
to Apache.
The request that Apache sends your subroutine may not be the original
request. For example, let's assume the client originally requested the file
/this_file_does_not/exist and Apache had been configured with an
ErrorDocument 404/mod-perl/my-script directive. The request that is
passed to your mod_perl module will be the one referencing the
/mod-perl/my-script request, not /this_file_does_not/exist. Luckily,
Apache keeps a record of each request, and every request object lets you
return a blessed reference to the next, last, main, and initial requests.
Let's see it all at work.
next page»