Show Contents Previous Page Next Page
Chapter 2 - A First Module "Hello World" with the Perl API Now that you have mod_perl installed, it's time to put the Perl
API through its paces. First you'll need to create a location for your Apache Perl modules to live.
If you haven't done so already, create a directory in some convenient place.
We suggest creating a lib subdirectory within the server root,
and a perl directory within that, making the full location ~www/lib/perl
(Unix), or C:\Apache\lib\perl (Win32). Within this directory, create
yet another directory for modules that live in the Apache:: namespace
(which will be the vast majority of the modules we write), namely ~www/lib/perl/Apache .
You'll now have to tell Apache where to look for these modules. mod_perl
uses the same include path mechanism to find required modules that Perl does,
and you can modify the default path either by setting the environment variable
PERL5LIB to a colon-delimited list of directories to search before
Apache starts up or by calling use lib '/ / / / '
when the interpreter is first launched. The first technique is most convenient
to use in conjunction with the PerlSetEnv directive, which sets an
environment variable. Place this directive somewhere early in your server configuration
file:
PerlSetEnv PERL5LIB /my/lib/perl:/other/lib/perl
Unfortunately this adds a little overhead to each request. Instead, we recommend
creating a Perl startup file that runs the use lib statement. You
can configure mod_perl to invoke a startup file of common Perl
commands each time the server is launched or restarted. This is the logical
place to put the use lib statement. Here's a small startup file
to get you started:
#!/usr/local/bin/perl
# modify the include path before we do anything else
BEGIN {
use Apache ();
use lib Apache->server_root_relative('lib/perl');
}
# commonly used modules
use Apache::Registry ();
use Apache::Constants();
use CGI qw(-compile :all);
use CGI::Carp ();
# put any other common modules here
# use Apache::DBI ();
# use LWP ();
# use DB_File ();
1;
This example startup file first modifies the include path to point to the
location of the Apache Perl module directory. It uses the Apache::server_root_relative()
method to turn the relative path into an absolute path that use lib
will honor. It then loads up some commonly used libraries, including Apache::Registry
(a fast CGI-like environment), Apache::Constants (various constants
used by Apache modules), and the CGI and CGI::Carp
modules. If most of your modules are going to use these libraries, loading them once
at start-up time makes sense and assures the absolute fastest performance of
your modules. Loading less-frequently used libraries should be deferred to the
time you actually need them. Save the startup file to some logical place. We recommend ~www/conf/startup.pl ,
so that it lives alongside Apache's other configuration files. If you can you
should make this file owned and only writable by root (Administrator on Win32
systems). This is because during the server startup phase the code in this file
is executed as the super-user, so anyone with write permissions to this file
(or the directory that contains it) effectively has super-user privileges. We'll need to tell Apache to run the startup file at launch time. Open perl.conf
(actually, any of the configuration files will do) and add the following lines
to the bottom:
PerlRequire conf/startup.pl
PerlFreshRestart On
The first directive tells Apache to load and run the startup script when it
is first launched. Like other file paths in Apache's configuration files, partial
paths are treated as relative to the server root. The second directive tells
the server to repeat this process every time it is restarted. This allows changes
to the startup script (and other Apache Perl modules) to take effect without
bringing the server completely down. You should now start or restart the server. On Unix platforms, the easiest
way to do this is to use the apachectl script located in ~www/bin .
The command apachectl graceful will send the server a polite USR1
signal to ask it to restart when it is finished processing all current requests,
while apachectl restart will issue the server a more imperative
HUP signal to command it to cancel all pending transaction and immediately restart.
In either case, the server will be launched if it isn't already running. Users
of the Win32 port can restart the server by issuing the command apache-k restart (Versions 1.3.3 and higher). If Apache is installed
as a Windows NT service, you may also restart it using the Services control
panel or by issuing the commands NET STOP APACHE and NET
START APACHE from within a command window. Watch the server ErrorLog during this process. If there are any
errors in the configuration file or the Perl startup file, you'll see messages
to that effect. Be particularly alert for messages like "Invalid Command `PerlRequire'."
This message means that you haven't actually launched a mod_perl -enabled
version of Apache. Are you sure that you launched the new executable? Now that everything's configured properly, you can write a module using the
Apache Perl API. Example 2-1 gives a basic one named
Apache::Hello for you to try out:
Example 2-1. A First Apache Perl Module
package Apache::Hello;
# File: Apache/Hello.pm
use strict;
use Apache::Constants qw(:common);
sub handler {
my $r = shift;
$r->content_type('text/html');
$r->send_http_header;
my $host = $r->get_remote_host;
$r->print(<<END);
<HTML>
<HEAD>
<TITLE>Hello There</TITLE>
</HEAD>
<BODY>
<H1>Hello $host</H1>
Who would take this book seriously if the first example didn't say "hello world"?
</BODY>
</HTML>
END
return OK;
}
1;
We'll go into the details in later chapters, but essentially, this module
contains the definition for a single subroutine named handler(). When
the time comes, Apache will invoke handler() to handle the request,
passing it an Apache request object stored in the variable $r .
The request object is the primary interface between subroutine and server. Using methods provided by the request object, our module first sets the MIME
content type of the outgoing data to text/html and then sends the HTTP
headers by calling send_http_header(). It retrieves the DNS name of
the remote host by making another call to the request object and incorporates
this value into a short HTML page that it sends to the browser by calling the
request object's print() method. At the end of the subroutine, the
module returns a value of OK (defined in the library module Apache::Constants)
to signal to Apache that execution was successful. To install this module, save it as ~www/lib/perl/Apache/Hello.pm
(C:\Apache\lib\perl\Apache\Hello.pm on Win32 systems). This makes
it accessible to mod_perl . The next step is to associate the module
with a URI by mapping it to a portion of your document tree.6
The simplest way to do this is by adding an Apache <Location>
directive to perl.conf (or any of the other configuration files,
for that matter). This entry will do the trick:
<Location /hello/world>
SetHandler perl-script
PerlHandler Apache::Hello
</Location>
The first directive, SetHandler perl-script, tells Apache to invoke
mod_perl to handle the phase of the HTTP transaction that produces
the content of the page. The second directive, PerlHandler Apache::Hello,
tells mod_perl to load the Apache::Hello module and
execute its handler() subroutine. Without this directive, you would
get a "File not found" error. The URI specified in <Location>
can be any arbitrary path on your system and doesn't (and probably shouldn't)
refer to a real file already in the document tree. If there already is a physical
document at that location, the Perl module will supersede it. You will have to restart the server again in order to have the new <Location>
section take effect. Later we will discuss how to install new modules without
restarting the server. Fire up your favorite browser and fetch the URI /hello/world .
You should be greeted by the page shown in Figure 2-1.
Figure 2-1. Apache::Hello results
If you get a server error of some sort, don't despair. Look in the server
error log for helpful messages from the Perl interpreter. They may be bare messages,
or if you are loading CGI::Carp in the Perl startup file, they
may be preceded by a timestamp and -e in the filename field, indicating
that the error occurred within a Perl eval() statement. Most of what
mod_perl does occurs within the context of an eval().
Most commonly you'll see messages about syntax errors. Fix the errors, restart
the server, and try again. If you get messages about not being able to find
the Apache::Hello module, most likely your include path is screwed
up. Check that the Perl startup script is setting the include path correctly,
that Apache/Hello.pm is installed in the correct subdirectory,
and that the permissions of Hello.pm and all its parent directories
give the Apache server user read access. Then restart the server and try again.
These are the basic steps for creating and installing a module using the Apache
Perl API. Later chapters will give you a more in-depth understanding of what's
going on here and how you can take advantage of it to do wonderful stuff. Footnotes 6 In the context of incoming Apache requests,
we use "URI" (Uniform Resource Identifier) rather than "URL" (Uniform Resource
Locator) throughout this book. URI is the more general term, so it can refer
to partial documents as well as to fully qualified URLs. The main reason, however,
is that URI is used in the Apache online documentation and in the names of API
function calls, and who are we to buck tradition? Show Contents Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |