How to use Apache's mod_perl
----------------------------

First things first
------------------
Where to get it: http://perl.apache.org/

How to compile it: Just follow the build instructions inside the mod_perl
documentation to compile Apache and mod_perl together; or, if you're a
hardcore Apache builder, or have some extra third-party modules, you can
do it yourself.

Once mod_perl is on, you can start using it right away.

How to use a mod_perl module to make CGI scripts faster
-------------------------------------------------------

You'll need to edit your httpd.conf to use mod_perl. You'll need to make a
Location tag to actually use mod_perl for your scripts; also an Alias
instead of your old ScriptAlias (because ScriptAlias forces the handler
used to be mod-cgi). It should look a bit like this:

#####
Alias /perl/ /where/my/cgi-scripts/are

PerlModule Apache::Registry # use module at startup for extra speed boost


   SetHandler perl-script
   PerlHandler Apache::Registry
   Options ExecCGI
   allow from all
   PerlSendHeader On

#####

The alias is whatever your ScriptAlias used to be. The PerlModule command
is just like a "use" that happens as soon as the server starts up (rather,
as soon as mod_perl is initialized).

Inside the location tag, we use SetHandler to tell Apache that this is a
mod_perl area, and tell mod_perl that we're using the Apache::Registry
module to run our CGI scripts. The ExecCGI option is necessary here just
like in normal CGI to make sure that Apache doesn't just send your
programs to the hapless surfer, and the "allow from all" is just an extra
configuration option to make sure nobody gets deprived of your great Perl
output.

PerlSendHeader On is a special configuration parameter to mod_perl that
you ONLY want to use for CGI scripts that had it done for them before
mod_perl. It tells mod_perl to have Apache send HTTP headers after parsing
your script headers. Turn it off if you have NPH (non-parsed-header)
scripts that send HTTP headers on their own, or when you're writing your
own 31337 m0d_p3r1 m0du13z that can send their own headers (coming up
soon).

The scripts you write here are just plain old CGI programs, so you don't
need to learn any new tricks (yet). Still, they should run quite a bit
quicker -- your script is secretly being wrapped up inside a sub and
getting called each time it's invoked, rather than starting perl up from
scratch, compiling your stuff, loading all those pesky modules, and so
forth.

If for some reason your script doesn't like to be mod_perl'ified (because
it uses explicit package variables which it doesn't clean up, and hence
doesn't get the clean slate it was expecting), you can replace
Apache::Registry with Apache::PerlRun. That still loads up Perl and all
your external modules at startup, but it re-compiles your scripts in a new
global context every time they're run. The tradeoff in ease of porting
vs. compilation time performance hit may be worth it if you have big
poorly-written hard-to-read CGI scripts out there.

Giving Configuration to your Scripts
------------------------------------

You're going to have to pass extra environment variables to those CGI
scripts one day; here's how.

The PerlSetEnv directive takes two arguments, variable name and value, and
puts them in %ENV when your CGI script runs. The PerlPassEnv directive
only takes one argument (variable name); it just makes sure the actual
value of the specified environment variable gets passed through to the CGI
script.

Cooler Stuff
------------

Now you've gotten to the point where you can use what most people call
"mod_perl" and make your crufty old CGI programs run really fast, and you
get to look cool because those /cgi-bin/ URLs have been turned into /perl/
URLs :p. But there's more ahead.

Using mod_perl to cache your CGI scripts is only a fraction of the power
of the module. You can specify your own Perl modules to do handle about
any portion of an HTTP request, and a vast library of interfaces to
Apache's internals at your disposal. In fact, with mod_perl you can do
just about anything you could do with your own C module for Apache.

How do you do all this cool stuff? Well, the first part is easy. First,
we'll stop writing CGI scripts and write handler modules. A handler module
is just an ordinary Perl module with a module function 'handler'. To use
it, change the "Apache::Registry" in the above httpd.conf to the name of
your module. The "handler" method gets called on every request to the
specified location. It takes a single argument (typically called $r, the
"request object") of a secret type -- it looks like an Apache object but
it's really a C object of type "request_rec *". That means it has some
methods you won't find if you look for them, unless you look really hard;
the documentation can be found in the manpage for the Apache module under
the THE REQUEST OBJECT section. The important ones:

* $r->send_http_header

Very important! Since you'll be turning off header parsing (by getting rid
of the PerlSendHeaders On line in your httpd.conf) you will need to send
your own headers. This is how you do that. It has to happen before any
other output.

* $r->content_type('text/plain')

Use this before sending the http header to set the content-type of your
output, so you don't have to print it out manually.

* $r->path_info()

Very useful for making a mod_perl module that looks like a whole directory
(Apache::Registry and Apache::PerlRun do this). It gives you everything in
your pathname after the Location tag, so if the Location is
/perl/mymodule/ and someone hits
http://your.server/perl/mymodule/action1?arg1=value1&arg2=value2 ,
path_info will give you "action1" and args will give you the usual hash.

* $r->args()

Absolutely vital! This one is like CGI::param; it returns a hash of key =>
value pairs in your query string in a list context (or the entire query
string when called in scalar context, if you go for that sort of
thing). You could also technically set the query-string with a parameter
here; that's useful if you're redirecting a POST and want to massage the
arguments a bit.

* $r->dir_config($param_name)

Get a value from the dir_config hash, which is set with the Apache
directive PerlSetVar key val; this is the preferred way of passing
configuration to mod_perl modules (rather than Perl{Set,Pass}Env).

* $r->header_out('WWW-Authenticate', 'Basic');

Sets a header whose name does not start with "Content". Content-***
headers have their own methods along the lines of content_type.

* $r->no_cache(bool)

Set this to set the No-Cache header -- important for highly dynamic data.

* $r->print(LIST)

You will use this more than you think you do -- mod_perl overrides the
default print() method with it. It works like print, but does the I/O in a
fashion more suitable for a webserver. NOTE: For secret reasons this
method doesn't work right when you print scalar references -- it
dereferences them before printing. If you want to print a scalar
reference, you have to use the scalar() operator (or concatenate an empty
string or otherwise stringify it) before printing it. On the other hand,
if you wanted to print a big scalar, you can be a bit quicker by printing
a reference to it instead.

* $r->send_fd($filehandle)

Dumps the open $filehandle to standard output. Great for printing a
dynamically-selected HTML chunk.

* $r->internal_redirect($internal-URI)

Does a *server-side* redirect to $internal-URI on your virtual server; the
client gets the contents he would have gotten with a real redirect but
doesn't have to make the extra round trip to the server for it.

All these things will help you write cooler web programs, but they're
still only about at the level of CGI, with just a couple minor bonuses
from your near-and-dear internal Apache calls. If you want to do even more
funky stuff, you can make extra handlers for different parts of the HTTP
request loop (and other obscure internal parts of Apache). You need to
compile in support for handlers at various phases when you run Makefile.PL
on mod_perl; then you can make PerlTransHandlers to handle filename
translations, PerlAuthenHandlers to do authentication, and all sorts of
weird stuff. If you want to do that you need to know a good bit about
Apache internals as well as more details about mod_perl; a good place to
find out about both of those is at http://perl.apache.org/.