Dynamic web content, the Perl/Apache way

Prerequisites

The first step is to get the Apache server working. Start with the Apache server web site.

The next step is to get mod_perl. See the mod_perl project page for more information.

Compiling and installing Apache and mod_perl is not terribly difficult, but it is outside the scope of this discussion. If you happen to be running Red Hat Linux, you can just install the apache and mod_perl rpms from the distribution. (Other Linux distributions probably have similar packages.) Note that there are gotchas to using any binary package, especially from older distributions. See the mod_perl Guide for more information.


Features of mod_perl

mod_perl embeds the Perl interpreter in the Apache server process, eliminating the start-up time and extra memory consumed with CGI (where the Apache process must fork() and exec() the Perl interpreter). In addition, on any modern operating system, the memory used in the parent Apache process for the Perl interpreter will be shared with the various child Apache processes.

mod_perl also allows for other nifty features, such as the ability to keep Perl bytecode in memory, eliminating the need to parse and compile scripts every time they are run.


Enabling mod_perl

If Apache is compiled with Dynamic Shared Object (DSO) support, simply add the following lines to httpd.conf:

LoadModule perl_module	modules/libperl.so
AddModule mod_perl.c
to load mod_perl when the Apache server starts.

To run perl scripts under mod_perl, you might add something like the following to httpd.conf:

Alias /perl/ /home/httpd/perl/
<Location /perl>
SetHandler perl-script
PerlHandler Apache::Registry
Options +ExecCGI
</Location>

There are two ways of running Perl scripts under mod_perl. The first is Apache::Registry, which was used in the above example. Scripts run under Apache::Registry are only parsed once, the first time they are accessed. The scripts never actually exit, so global variables keep their values, network connections are not closed automatically, etc.

The second way of running Perl scripts under mod_perl is to use Apache::PerlRun in place of Apache::Registry. Apache::PerlRun does not cache the scripts it runs, so existing CGI scripts can be run unmodified under mod_perl.


Embedding Perl in HTML

There are several mod_perl modules for embedding Perl code into HTML documents, including HTML::Embperl, HTML::Mason, and Apache::ASP. Personally, I've found that the easiest to implement was Apache::ePerl, which is a specialized, mod_perl-enabled version of ePerl, a modified Perl interpreter that allows you to embed Perl code into any type of ASCII text.

To install Apache::ePerl, simply do install Bundle::Apache in the CPAN shell (perl -MCPAN -e shell). Bundle::Apache contains several things, including Apache::ePerl.

To enable Apache::ePerl parsing of, for example, any HTML document (*.html) in /home/httpd/html/, you would simply include something like the following in httpd.conf:

PerlModule Apache::ePerl
<Perl>
$Apache::ePerl::Config->{'BeginDelimiter'}  = '<:';
$Apache::ePerl::Config->{'EndDelimiter'}    = ':>';
$Apache::ePerl::Config->{'CaseDelimiters'}  = 0;
$Apache::ePerl::Config->{'ConvertEntities'} = 0;
</Perl>
<Location ~ "^/+[^/]*\.html$">
  Options +ExecCGI
  SetHandler perl-script
  PerlHandler Apache::ePerl
</Location>

Note that BeginDelimiter and EndDelimiter can be anything you want. I generally choose <: and :> to have something relatively obvious and balanced that doesn't conflict with <? ?> and <% %>, which are used by PHP and ASP.

With Apache::ePerl enabled, a simple document like this:

<html>
<body>
<p>The time is now <: print scalar(localtime); :>.</p>
</body>
</html>
would be presented to the browser like this:
<html>
<body>
<p>The time is now Thu Feb  3 11:29:24 2000.</p>
</body>
</html>