-X
?
Mod_perl_faq - frequently asked questions about mod_perl ($Date: 2001/06/02 13:54:54 $)
Mod_perl allows an Apache Web Server to directly execute perl code. This document is designed to answer questions that arise when designing new applications, and converting existing applications, to run in the mod_perl environment.
The Apache/Perl integration project brings together the full power of the Perl programming language and the Apache HTTP server. This is achieved by linking the Perl runtime library into the server and providing an object-oriented Perl interface to the server's C language API.
Mod_perl is a bundle of software. One part of the bundle is designed to be compiled and linked together with Apache and Perl. The remainder is perl code that provides the object-oriented interface to the ``perl-enabled'' web server.
The primary advantages of mod_perl are power and speed. You have full access to the inner-workings of the web server and can intervene at any stage of request-processing. This allows for customized processing of (to name just a few of the phases) URI->filename translation, authentication, response generation and logging. There is very little run-time overhead. In particular, it is not necessary to start a separate process, as is often done with web-server extensions. The most wide-spread such extension mechanism, the Common Gateway Interface (CGI), can be replaced entirely with perl-code that handles the response generation phase of request processing. Mod_perl includes a general purpose module for this purpose (Apache::Registry) that can transparently run existing perl CGI scripts.
Mod_perl can be found at http://www.perl.com/CPAN/modules/by-module/Apache/
Win32 users note: mod_perl compiles cleanly and works with ActivePerl (build 626, June 2001). In http://www.mail-archive.com/[email protected]/msg11513.html Randy Kobes wrote:
A ppd for mod_perl, suitable for use with ActivePerls based on Perl-5.6.0, is now available. Installation is as ppm install
http://theoryx5.uwinnipeg.ca/ppmpackages/mod_perl.ppd
or in ftp://theoryx5.uwinnipeg.ca/pub/ppmpackages/. A post-install script will subsequently be run which will download and install the required ApacheModulePerl.dll; this should be placed in your Apache modules directory. If for some reason the script fails, this dll can be obtained from http://theoryx5.uwinnipeg.ca/ppmpackages/. Also available in this directory is a sample Apache httpd.conf suitable to test mod_perl on Win32.
Configuring and installing apache with mod_perl is a complex process, so it is really not a good idea to attempt to do it manually. If you are used to configuring third-party modules into Apache using the apache configuration process, please realize that running mod_perl's Makefile.PL with the right parameters does this for you.
Read the INSTALL* files in the top-level mod_perl distribution
directory and then choose one of the INSTALL.simple* recipes that is
close to your requirements, as a starting point. When you succeed in
compiling and linking an httpd, a quick way to check that everything
is configured according to plan is to run it with the -l
(list
compiled-in modules) and -V
(show paths) flags.
The mod_perl documentation in mod_perl.pod. After you have installed
mod_perl you can read it with the command: perldoc mod_perl
.
The complete list of available documentation can be found at the end of mod_perl's README file.
If you are using mod_perl to extend the server functionality, you will
need to read perldoc Apache
and the Apache API notes, which can be
found in apache_x.x.x/htdocs/manual/misc/API.html.
Existing (perl-) CGI scripts should run as-is under mod_perl. There are a
number of reasons why they may need to be adjusted, and these are
discussed later in this FAQ. If you are developing a new CGI script it is
probably best to use CGI.pm. It is part of the standard perl distribution
and its documentation can be read with the command: perldoc CGI
.
Refer to the mod_perl_cgi FAQ for tips on writing and converting CGI scripts for mod_perl.
Interfacing with Apache is discussed in the mod_perl_api FAQ.
Because mod_perl runs within an httpd child process, it runs with the user-id and group-id specified in the httpd.conf file. This user/group should have the lowest possible privileges. It should only have access to world readable files. Even so, careless scripts can give away information. You would not want your /etc/passwd file to be readable over the net, for instance.
Different mod_perl scripts run successively using the same Perl interpreter instance. So, in addition to classical CGI mischiefs, a malicious mod_perl script can redefine any Perl object and change the behavior of other mod_perl scripts.
If you turn on tainting checks, perl can help you to avoid the pitfalls of
using data received from the net. Setting the -T
switch on the first line
of the script is not sufficient to enable tainting checks under mod_perl.
You have to include the directive PerlTaintCheck On
in the httpd.conf
file.
You will have to start a new process that runs under a suitable user-id (or group-id). If all requests handled by the script will need the higher privileges, you might as well write it as a suid CGI script. Read the documentation about suEXEC in the Apache documentation.
Alternatively, pre-process the request with mod_perl and fork a suid helper process to handle the privileged part of the task.
Read the section on ``Memory Consumption'' in the mod_perl.pod.
Make sure that your scripts are not leaking memory. Global variables
stay around indefinitely, lexical variables (declared with my())
are
destroyed when they go out of scope, provided there are no references
to them from outside of that scope. The Apache::Leak module can warn
about some types of memory leak.
To get information about the modules that have been loaded and their symbol-tables, use the Apache::Status module. It is enabled by adding these lines to the httpd configuration file.
<Location /perl-status> SetHandler perl-script PerlHandler Apache::Status </Location>
Then look at the URL http://www.your.host/perl-status
Joel Wagner reports that calling an undefined subroutine in a module can cause a tight loop that consumes all memory. Here is a way to catch such errors. Define an autoload subroutine
sub UNIVERSAL::AUTOLOAD { my $class = shift; warn "$class can't `$UNIVERSAL::AUTOLOAD'!\n"; }
It will produce a nice error in error_log, giving the line number of the call and the name of the undefined subroutine.
Apache::Registry checks the timestamp of scripts that it has loaded and reloads them if they change. Other handlers and library modules are not automatically reloaded by mod_perl, but you can use the Apache::StatINC module to do this for you.
Andreas Koenig writes:
LWP comes with debugging capabilities that are sometimes better than
your browser, sometimes your browser is the better testing
device. Make sure you can call lwp-request from the command line and
have your browser ready before you start. I find the -x
switch
(extended debugging) and the -d
switch (do not display content) most
useful.
lwp-request -xd http://your.server/test/file.not_there
Carefully examine if the status is 404 and if the headers look good.
If you try 'lwp-request -es', the HTML output will not be the one you
are sending, instead lwp-request will send its own cooked HTML text
(as of version libwww-perl-5.09). Check the real text either with the
-x
switch or with telnet or your browser.
ErrorDocument 404 /perl/errors/err404-01
The /perl/ directory is configured to
<Location /perl> SetHandler perl-script PerlHandler Apache::Registry::handler Options ExecCGI </Location>
I have no PerlSendHeader and no PerlNewSendHeader directive in any configuration file.
The following works fine for me:
my $r = Apache->request; $r->content_type('text/html; charset=ISO-8859-1'); $r->send_http_header; $r->status(200); ...send other HTML stuff...
At the time of the send_http_header we have an error condition of type 404--this is what gets sent to the browser. After that I set status to 200 to silence the apache engine.
I was not successful in trying to do the same with CGI.pm, but I didn't try very hard.
If you put your modules into one of the directories on perl's search path (the @INC array), they will be found automatically. Traditionally, site-specific modules go in /usr/lib/perl5/site_perl/. Newer versions of mod_perl add the directory $ServerRoot/lib/perl to @INC on startup so that is a good place for modules that are only used by mod_perl scripts.
If you need to load files from other non-standard locations, you can add directories to the @INC array with a 'use lib' statement in a startup script. See mod_perl_tuning for an example.
Following the documentation, I have put the following in the html file:
<!--#perl sub="Apache::Include" arg="/perl/ssi.pl" -->
I want to send an argument to the ssi.pl script. How?
It won't work with Apache::Include. Instead of a script, define a subroutine that's pulled in with PerlRequire or PerlModule, like so:
sub My::ssi { my($r, $one, $two, $three) = @_; ... }
In the html file:
<!--#perl sub="My::ssi" arg="one" arg="two" arg="three" -->
-X
?If you use Netscape while your server is running in single-process mode, the ``KeepAlive'' feature gets in the way. Netscape tries to open multiple connections and keep them open. Because there is only one server process listening, each connection has to time-out before the next succeeds. Turn off KeepAlive in httpd.conf to avoid this effect.
If you sometimes see error messages like this:
[Thu Sep 11 11:03:06 1997] Undefined subroutine &Apache::ROOT::perl::script1::sub_foo called at /some/path/perl/script2 line 42.
despite the fact that script2 normally works just fine, it looks like you have a namespace problem in a library file. If sub_foo is located in a file that is pulled in by 'require' and both script1 and script2 require it, you need to be sure that the file containing sub_foo sets a package name. Otherwise, sub_foo gets defined in the namespace that is active the first time it is required, and the next require is a no-op because that file is already in %INC. The same problem can happen with global variables.
The solution is simple, set up your require'd file something along these lines:
package SomeName;
sub sub_foo {...}
Now, have scripts call SomeName::sub_foo() instead of sub_foo().
You may see httpd child processes crashing with segmentation fault when you restart the server with a HUP or USR1 signal. This is not a bug in mod_perl. If you have 'PerlFreshRestart On' in the configuration, the main httpd daemon reloads all the perl modules that it has preloaded when it gets a HUP or USR1 signal. Unfortunately, not all perl modules are robust enough to survive this, for them, unusual situation.
Some people have seen error messages such as this:
[Fri Sep 26 10:50:08 1997] (in cleanup) no dbproc key in hash at /usr/lib/perl5/site_perl/Apache/Registry.pm line 119.
Doug writes:
``I have yet to figure out why, but there have been a few arbitrary cases where Perl (in mod_perl) _insists_ on finding and/or calling a DESTROY method for an object. Defining an empty sub DESTROY has been the bandaid for these few cases.''
If the specific error message gives you a hint about which object is
causing difficulty, put the sub DESTROY { }
in the module that
defines that object class.
There are 2 environment variables you can test.
exists $ENV{"MOD_PERL"} # if running under mod_perl
$ENV{"GATEWAY_INTERFACE"} eq "CGI-Perl/1.1"
The MOD_PERL variable gets set immediately when the perl interpreter starts up, whereas GATEWAY_INTERFACE may not be set yet when BEGIN blocks are being processed.
The Perl tie'd filehandle interface is not complete, format/write is
one of the missing pieces. If you configure Perl with sfio, write()
should work just fine.
There is a mailing-list dedicated to mod_perl. It is archived at http://outside.organic.com/mail-archives/modperl/ and at http://forum.swarthmore.edu/epigone/modperl (which has a search engine) and also at http://www.progressive-comp.com/Lists/?l=apache-modperl&r=1#apache-modperl (threaded and indexed).
You can subscribe to the list by sending a mail to
[email protected]
and responding to the confirmation
message that you will receive. To unsubscribe, send mail to
[email protected]
from the address you are
subscribed at and reply to the confirmation message. Look at the
full headers of mails that you receive from the list to see the
address that they were sent to. The address is embedded in the
Return-Path
header (you will probably have to activate a ``show full
headers'' function in your mail reader to see it). To find the
address, delete modperl-return-nnnn-
from the front of the return path
and @apache.org
from the back, then replace the =
with @
.
Remember: the mailing list is for questions about and discussion of mod_perl. Quetions about perl programming in general should be asked in the newsgroup comp.lang.perl.misc, after consulting the fine perl faqs. There is a whole set of newsgroups dedicated to web authoring, web servers etc.: comp.infosystems.www.*
The mod_perl homepage http://perl.apache.org/ has links to other mod_perl resources.
The pod source of this FAQ is available at http://www.ping.de/~fdc/mod_perl/mod_perl_faq.tar.gz