24.5. Configuring mod_perl 2.0Similar to mod_perl 1.0, in order to use mod_perl 2.0 a few configuration settings should be added to httpd.conf. They are quite similar to the 1.0 settings, but some directives were renamed and new directives were added. 24.5.1. Enabling mod_perlTo enable mod_perl as a DSO, add this to httpd.conf: LoadModule perl_module modules/mod_perl.so This setting specifies the location of the mod_perl module relative to the ServerRootsetting, so you should put it somewhere after ServerRoot is specified. Win32 users need to make sure that the path to the Perl binary (e.g., C:\Perl\bin) is in the PATH environment variable. You could also add the directive: LoadFile "/Path/to/your/Perl/bin/perl5x.dll" to httpd.conf to load your Perl DLL, before loading mod_perl.so. 24.5.2. Accessing the mod_perl 2.0 ModulesTo prevent you from inadvertently loading mod_perl 1.0 modules, mod_perl 2.0 Perl modules are installed into dedicated directories under Apache2/. The Apache2 module prepends the locations of the mod_perl 2.0 libraries to @INC: @INC is the same as the core @INC, but with Apache2/ prepended. This module has to be loaded just after mod_perl has been enabled. This can be accomplished with: use Apache2 ( ); in the startup file. If you don't use a startup file, you can add: PerlModule Apache2 to httpd.conf, due to the order in which the PerlRequire and PerlModule directives are processed. 24.5.3. Startup FileNext, a startup file with Perl code usually is loaded: PerlRequire "/home/httpd/httpd-2.0/perl/startup.pl" It's used to adjust Perl module search paths in @INC, preload commonly used modules, precompile constants, etc. A typical startup.pl file for mod_perl 2.0 is shown in Example 24-1. Example 24-1. startup.pluse Apache2 ( ); use lib qw(/home/httpd/perl); # enable if the mod_perl 1.0 compatibility is needed # use Apache::compat ( ); # preload all mp2 modules # use ModPerl::MethodLookup; # ModPerl::MethodLookup::preload_all_modules( ); use ModPerl::Util ( ); #for CORE::GLOBAL::exit use Apache::RequestRec ( ); use Apache::RequestIO ( ); use Apache::RequestUtil ( ); use Apache::Server ( ); use Apache::ServerUtil ( ); use Apache::Connection ( ); use Apache::Log ( ); use APR::Table ( ); use ModPerl::Registry ( ); use Apache::Const -compile => ':common'; use APR::Const -compile => ':common'; 1; In this file the Apache2 module is loaded, so the 2.0 modules will be found. Afterwards, @INC is adjusted to include nonstandard directories with Perl modules: use lib qw(/home/httpd/perl); If you need to use the backward-compatibility layer, to get 1.0 modules that haven't yet been ported to work with mod_perl 2.0, load Apache::compat: use Apache::compat ( ); Next, preload the commonly used mod_perl 2.0 modules and precompile the common constants. You can preload all mod_perl 2.0 modules by uncommenting the following two lines: use ModPerl::MethodLookup; ModPerl::MethodLookup::preload_all_modules( ); Finally, the startup.pl file must be terminated with 1;. 24.5.4. Perl's Command-Line SwitchesNow you can pass Perl's command-line switches in httpd.conf by using the PerlSwitches directive, instead of using complicated workarounds. For example, to enable warnings and taint checking, add: PerlSwitches -wT The -I command-line switch can be used to adjust @INC values: PerlSwitches -I/home/stas/modperl For example, you can use that technique to set different @INC values for different virtual hosts, as we will see later. 24.5.5. mod_perl 2.0 Core Handlersmod_perl 2.0 provides two types of core handlers: modperl and perl-script. 24.5.5.1. modperlmodperl is configured as: SetHandler modperl This is the bare mod_perl handler type, which just calls the Perl*Handler's callback function. If you don't need the features provided by the perl-script handler, with the modperl handler, you can gain even more performance. (This handler isn't available in mod_perl 1.0.) Unless the Perl*Handler callback running under the modperl handler is configured with: PerlOptions +SetupEnv or calls: $r->subprocess_env; in a void context (which has the same effect as PerlOptions +SetupEnv for the handler that called it), only the following environment variables are accessible via %ENV:
Therefore, if you don't want to add the overhead of populating %ENV when you simply want to pass some configuration variables from httpd.conf, consider using PerlSetVar and PerlAddVar instead of PerlSetEnv and PerlPassEnv. 24.5.5.2. perl-scriptSetHandler perl-script Most mod_perl handlers use the perl-script handler. Here are a few things to note:
24.5.5.3. A simple response handler exampleLet's demonstrate the differences between the modperl and perl-script core handlers. Example 24-2 represents a simple mod_perl response handler that prints out the environment variables as seen by it. Example 24-2. Apache/PrintEnv1.pmpackage Apache::PrintEnv1; use strict; use warnings; use Apache::RequestRec ( ); # for $r->content_type use Apache::Const -compile => 'OK'; sub handler { my $r = shift; $r->content_type('text/plain'); for (sort keys %ENV){ print "$_ => $ENV{$_}\n"; } return Apache::OK; } 1; This is the required configuration for the perl-script handler: PerlModule Apache::PrintEnv1 <Location /print_env1> SetHandler perl-script PerlResponseHandler Apache::PrintEnv1 </Location> Now issue a request to http://localhost/print_env1, and you should see all the environment variables printed out. The same response handler, adjusted to work with the modperl core handler, is shown in Example 24-3. Example 24-3. Apache/PrintEnv2.pmpackage Apache::PrintEnv2; use strict; use warnings; use Apache::RequestRec ( ); # for $r->content_type use Apache::RequestIO ( ); # for $r->print use Apache::Const -compile => 'OK'; sub handler { my $r = shift; $r->content_type('text/plain'); $r->subprocess_env; for (sort keys %ENV){ $r->print("$_ => $ENV{$_}\n"); } return Apache::OK; } 1; The configuration now will look like this: PerlModule Apache::PrintEnv2 <Location /print_env2> SetHandler modperl PerlResponseHandler Apache::PrintEnv2 </Location> Apache::PrintEnv2 cannot use print( ), so it uses $r->print( ) to generate a response. Under the modperl core handler, %ENV is not populated by default; therefore, subprocess_env( ) is called in a void context. Alternatively, we could configure this section to do: PerlOptions +SetupEnv If you issue a request to http://localhost/print_env2, you should see all the environment variables printed out as with http://localhost/print_env1. 24.5.6. PerlOptions DirectiveThe PerlOptions directive provides fine-grained configuration for what were compile-time-only options in the first mod_perl generation. It also provides control over what class of PerlInterpreter is used for a <VirtualHost> or location configured with <Location>, <Directory>, etc. Options are enabled by prepending + and disabled with -. The options are discussed in the following sections. 24.5.6.1. EnableOn by default; can be used to disable mod_perl for a given <VirtualHost>. For example: <VirtualHost ...> PerlOptions -Enable </VirtualHost> 24.5.6.2. CloneShare the parent Perl interpreter, but give the <VirtualHost> its own interpreter pool. For example, should you wish to fine-tune interpreter pools for a given virtual host: <VirtualHost ...> PerlOptions +Clone PerlInterpStart 2 PerlInterpMax 2 </VirtualHost> This might be worthwhile in the case where certain hosts have their own sets of large modules, used only in each host. Tuning each host to have its own pool means that the hosts will continue to reuse the Perl allocations in their specific modules. When cloning a Perl interpreter, to inherit the parent Perl interpreter's PerlSwitches, use: <VirtualHost ...> ... PerlSwitches +inherit </VirtualHost> 24.5.6.3. ParentCreate a new parent Perl interpreter for the given <VirtualHost> and give it its own interpreter pool (implies the Clone option). A common problem with mod_perl 1.0 was that the namespace was shared by all code within the process. Consider two developers using the same server, each of whom wants to run a different version of a module with the same name. This example will create two parent Perl interpreters, one for each <VirtualHost>, each with its own namespace and pointing to a different path in @INC: <VirtualHost ...> ServerName dev1 PerlOptions +Parent PerlSwitches -Mblib=/home/dev1/lib/perl </VirtualHost> <VirtualHost ...> ServerName dev2 PerlOptions +Parent PerlSwitches -Mblib=/home/dev2/lib/perl </VirtualHost> 24.5.6.4. Perl*HandlerDisable specific Perl*Handlers (all compiled-in handlers are enabled by default). The option name is derived from the Perl*Handler name, by stripping the Perl and Handler parts of the word. So PerlLogHandler becomes Log, which can be used to disable PerlLogHandler: PerlOptions -Log Suppose one of the hosts does not want to allow users to configure PerlAuthenHandler, PerlAuthzHandler, PerlAccessHandler, and <Perl>sections: <VirtualHost ...> PerlOptions -Authen -Authz -Access -Sections </VirtualHost> Or maybe it doesn't want users to configure anything but the response handler: <VirtualHost ...> PerlOptions None +Response </VirtualHost> 24.5.6.5. AutoLoadResolve Perl*Handlers at startup time; loads the modules from disk if they're not already loaded. In mod_perl 1.0, configured Perl*Handlers that are not fully qualified subroutine names are resolved at request time, loading the handler module from disk if needed. In mod_perl 2.0, configured Perl*Handlers are resolved at startup time. By default, modules are not auto-loaded during startup-time resolution. It is possible to enable this feature with: PerlOptions +Autoload Consider this configuration: PerlResponseHandler Apache::Magick In this case, Apache::Magick is the package name, and the subroutine name will default to handler. If the Apache::Magick module is not already loaded, PerlOptions +Autoload will attempt to pull it in at startup time. With this option enabled you don't have to explicitly load the handler modules. For example, you don't need to add: PerlModule Apache::Magick 24.5.6.6. GlobalRequestSet up the global Apache::RequestRec object for use with Apache->request. This setting is needed, for example, if you use CGI.pm to process the incoming request. This setting is enabled by default for sections configured as: <Location ...> SetHandler perl-script ... </Location> And can be disabled with: <Location ...> SetHandler perl-script PerlOptions -GlobalRequest ... </Location> 24.5.6.7. ParseHeadersScan output for HTTP headers. This option provides the same functionality as mod_perl 1.0's PerlSendHeaders option, but it's more robust. It usually must be enabled for registry scripts that send the HTTP header with: print "Content-type: text/html\n\n"; 24.5.6.8. MergeHandlersTurn on merging of Perl*Handler arrays. For example, with this setting: PerlFixupHandler Apache::FixupA <Location /inside> PerlFixupHandler Apache::FixupB </Location> a request for /inside runs only Apache::FixupB (mod_perl 1.0 behavior). But with this configuration: PerlFixupHandler Apache::FixupA <Location /inside> PerlOptions +MergeHandlers PerlFixupHandler Apache::FixupB </Location> a request for /inside will run both the Apache::FixupA and Apache::FixupB handlers. 24.5.6.9. SetupEnvSet up environment variables for each request, à la mod_cgi. When this option is enabled, mod_perl fiddles with the environment to make it appear as if the code is called under the mod_cgi handler. For example, the $ENV{QUERY_STRING} environment variable is initialized with the contents of Apache::args( ), and the value returned by Apache::server_hostname( ) is put into $ENV{SERVER_NAME}. Those who have moved to the mod_perl API no longer need this extra %ENV population and can gain by disabling it, since %ENV population is expensive. Code using the CGI.pm module requires PerlOptions +SetupEnv because that module relies on a properly populated CGI environment table. This option is enabled by default for sections configured as: <Location ...> SetHandler perl-script ... </Location> Since this option adds an overhead to each request, if you don't need this functionality you can turn it off for a certain section: <Location ...> SetHandler perl-script PerlOptions -SetupEnv ... </Location> or globally affect the whole server: PerlOptions -SetupEnv <Location ...> ... </Location> It can still be enabled for sections that need this functionality. When this option is disabled you can still read environment variables set by you. For example, when you use the following configuration: PerlOptions -SetupEnv <Location /perl> PerlSetEnv TEST hi SetHandler perl-script PerlHandler ModPerl::Registry Options +ExecCGI </Location> and you issue a request for setupenvoff.pl from Example 24-4. Example 24-4. setupenvoff.pluse Data::Dumper; my $r = Apache->request( ); $r->send_http_header('text/plain'); print Dumper(\%ENV); you should see something like this: $VAR1 = { 'GATEWAY_INTERFACE' => 'CGI-Perl/1.1', 'MOD_PERL' => 'mod_perl/2.0.1', 'PATH' => '/bin:/usr/bin', 'TEST' => 'hi' }; Notice that we got the value of the environment variable TEST. 24.5.7. Thread-Mode-Specific DirectivesThe following directives are enabled only in a threaded MPM mod_perl: 24.5.7.1. PerlInterpStartThe number of interpreters to clone at startup time. 24.5.7.2. PerlInterpMaxIf all running interpreters are in use, mod_perl will clone new interpreters to handle the request, up until this number of interpreters is reached. When PerlInterpMax is reached, mod_perl will block until an interpreter becomes available. 24.5.7.3. PerlInterpMinSpareThe minimum number of available interpreters this parameter will clone before a request comes in. 24.5.7.4. PerlInterpMaxSparemod_perl will throttle down the number of interpreters to this number as those in use become available. 24.5.7.5. PerlInterpMaxRequestsThe maximum number of requests an interpreter should serve. The interpreter is destroyed and replaced with a fresh clone when this number is reached. 24.5.7.6. PerlInterpScopeAs mentioned, when a request in a threaded MPM is handled by mod_perl, an interpreter must be pulled from the interpreter pool. The interpreter is then available only to the thread that selected it, until it is released back into the interpreter pool. By default, an interpreter will be held for the lifetime of the request, equivalent to this configuration: PerlInterpScope request For example, if a PerlAccessHandler is configured, an interpreter will be selected before it is run and not released until after the logging phase. Interpreters will be shared across subrequests by default; however, it is possible to configure the interpreter scope to be per subrequest on a per-directory basis: PerlInterpScope subrequest With this configuration, an autoindex-generated page, for example, would select an interpreter for each item in the listing that is configured with a Perl*Handler. It is also possible to configure the scope to be per handler: PerlInterpScope handler With this configuration, an interpreter will be selected before PerlAccessHandlers are run and put back immediately afterwards, before Apache moves on to the authentication phase. If a PerlFixupHandler is configured further down the chain, another interpreter will be selected and again put back afterwards, before PerlResponseHandler is run. For protocol handlers, the interpreter is held for the lifetime of the connection. However, a C protocol module (e.g., mod_ftp) might hook into mod_perl and provide a request_rec record. In this case, the default scope is that of the request (the download of one file). Should a mod_perl handler want to maintain state for the lifetime of an FTP connection, it is possible to do so on a per-<VirtualHost> basis: PerlInterpScope connection 24.5.8. Retrieving Server Startup OptionsThe httpd server startup options can be retrieved using Apache::exists_config_define( ). For example, to check if the server was started in single-process mode: panic% httpd -DONE_PROCESS use the following code: if (Apache::exists_config_define("ONE_PROCESS")) { print "Running in a single process mode"; } Copyright © 2003 O'Reilly & Associates. All rights reserved. |
|