Migrating from mod_perl 1.0 to mod_perl 2.0
This chapter explains how to port code from mod_perl 1.0 to mod_perl 2.0.
To migrate the configuration files to the mod_perl 2.0 syntax, you may need to do certain adjustments if you use any of the configuration directives listed in the following sections.
Remember that if you use any of the new directives, your configuration won't work anymore with mod_perl 1.0.
PerlHandler
PerlHandler was replaced with PerlResponseHandler.
PerlResponseHandler
PerlSendHeader
PerlSendHeader was replaced with PerlOptions +/-ParseHeaders directive.
PerlOptions +/-ParseHeaders
PerlSendHeader On => Options +ParseHeaders PerlSendHeader Off => Options -ParseHeaders
PerlSetupEnv
PerlSetupEnv was replaced with PerlOptions +/-SetupEnv directive.
PerlOptions +/-SetupEnv
PerlSetupEnv On => Options +SetupEnv PerlSetupEnv Off => Options -SetupEnv
PerlTaintCheck
The tainting mode now can be turned on with:
PerlSwitches -T
The default is Off. You cannot turn it Off once it's turned On.
PerlWarn
Warnings now can be enabled globally with:
PerlSwitches -w
mod_perl 2.0 is trying hard to be back compatible with mod_perl 1.0. However some things (mostly APIs) have been changed. In order to gain a complete compatibilty with 1.0 while running under 2.0, you should load the compatibility module as early as possible:
use Apache::compat;
at the server startup. And unless there are forgotten things or bugs, your code should work without any changes under 2.0 series.
If you have mod_perl 1.0 and 2.0 installed on the same system and the two use the same perl libraries directories (e.g. /usr/lib/perl5), make sure to load first the Apache2 module which will perform the necessary adjustments to @INC.
Apache2
@INC
use Apache2; # if you have 1.0 and 2.0 installed use Apache::compat;
However, unless you want to keep the 1.0 compatibility, you should try to remove the compatibility layer and adjust your code to work under 2.0 without it. You want to do it mainly for the performance improvement.
This document explains what APIs have changed and what new APIs should be used instead.
Apache::Registry
Apache::Registry, Apache::PerlRun and other modules from the registry family now live in the ModPerl:: namespace to avoid collisions with the versions from 1.0.
Apache::PerlRun
ModPerl::
To run the Apache::Registry module from mod_perl 1.0 you have to load Apache::compat at the startup:
Apache::compat
file:startup.pl: ---------------- use Apache2; # if you have 1.0 and 2.0 installed use Apache::compat (); use lib ...; # to find 1.0x Apache::Registry
then in httpd.conf:
Alias /perl /path/to/perl/scripts <Location /perl> Options +ExecCGI SetHandler perl-script PerlResponseHandler Apache::Registry </Location>
Notice that Apache::compat has to be loaded before CGI.pm if the latter module is used.
CGI.pm
META: complete
Apache::Constants
Apache::Constants has been replaced by three classes:
Apache::Const
Apache constants
APR::Const
Apache Portable Runtime constants
ModPerl::Const
mod_perl specific constants
See the manpages of the respective modules to figure out which constants they provide. (XXX: the manpages don't exist)
META: add the info how to perform the transition. XXX: may be write a script, which can tell you how to port the constants to 2.0? Currently Apache::compat doesn't provide a complete back compatibility layer.
Apache::
$r->content()
$r->args()
$r->args() in 2.0 returns the query string without parsing and splitting it into an array. You can also set the query string by passing a string to this method.
$r->content() and $r->args() in an array context were mistakes that never should have been part of the mod_perl 1.0 API. There multiple reason for that, among others:
does not handle multi-value keys
does not handle multi-part content types
does not handle chunked encoding
slurps $r->headers_in->{'content-length'} into a single buffer (bad for performance, memory bloat, possible dos attack, etc.)
$r->headers_in->{'content-length'}
in general duplicates functionality (and does so poorly) that is done better in Apache::Request.
Apache::Request
if one wishes to simply read POST data, there is the more modern {setup,should,get}_client_block API, and even more modern filter API. Along with continued support for read(STDIN, ...) and $r->read($buf, $r->headers_in->{'content-length'})
{setup,should,get}_client_block
read(STDIN, ...)
$r->read($buf, $r->headers_in->{'content-length'}
Instead you should use Apache::Request's params() and similar methods to do the parsing for you. See the Apache::Request manpage.
XXX: ...when Apache::Request will be ported to 2.0. For now you can use the code in Apache::compat that implements these methods in Perl.
chdir_file()
chdir() is not a thread-safe function, therefore chdir_file() is gone from the API.
chdir()
$r->connection->user
This method is deprecated in 1.0 and $r->user should be used instead for both versions of mod_perl. Apache::user() method is available since mod_perl version 1.24_01.
$r->user
Apache::user()
exit()
Apache::exit() has been replaced with ModPerl::Util::exit(), which is a function (not a method) and accepts a single optional argument: status, whose default is 0 (== do nothing).
Apache::exit()
ModPerl::Util::exit()
See the ModPerl::Util manpage.
finfo()
XXX: not implemented yet. To be implemented. Apache::compat handles that for now with:
sub finfo { my $r = shift; stat $r->filename; \*_; }
gensym()
Since Perl 5.6.1 filehandlers are autovivified and there is no need for Apache::gensym() function, since now it can be done with:
Apache::gensym()
open my $fh, "foo" or die $!;
Though the C function modperl_perl_gensym() is available for XS/C extensions writers.
header_in()
header_out()
err_header_out()
header_in(), header_out() and err_header_out() are not available in 2.0. Use headers_in(), headers_out() and err_headers_out() instead (which should be used in 1.0 as well). For example you need to replace:
headers_in()
headers_out()
err_headers_out()
$r->err_header_out("Pragma" => "no-cache");
with:
$r->err_headers_out->{'Pragma'} = "no-cache";
See the Apache::RequestRec manpage.
log_reason()
log_reason() has been replaced with a set of dedicated functions: Apache::RequestRec::log_error(), Apache::ServerRec::log_error(), Apache::Log::info() and others.
Apache::RequestRec::log_error()
Apache::ServerRec::log_error()
Apache::Log::info()
See the Apache::RequestRec, Apache::Server and Apache::Log manpages.
module()
Apache::module has been replaced with the function Apache::Module::loaded(), which now accepts a single argument: the module name.
Apache::module
Apache::Module::loaded()
register_cleanup()
register_cleanup() has been replaced with APR::Pool::cleanup_register() which accepts the pool object as the first argument instead of the request object. e.g.:
APR::Pool::cleanup_register()
$r->pool->cleanup_register(\&cleanup, $data);
where the last argument $data is optional.
$data
See the APR::Pool manpage.
$r->request()
Use Apache::request().
Apache::request()
Notice that Apache->request is deprecated. It's error-prone and hurts performance when using threaded MPMs, since it has to use thread local storage.
Apache->request
For any location that uses Apache->request and uses "modperl" handler, you need to configure:
"modperl"
<Location ...> SetHandler modperl PerlOptions +GlobalRequest ... </Location>
It's already enabled for:
<Location ...> SetHandler perl-script ... </Location>
send_fd()
send_fd_length()
currently available only in the 1.0 compatibility layer. The problem is that Apache has changed the API and the its functionality. See the implementation in Apache::compat.
XXX: needs a better resolution
$r->server_root_relative
Apache::server_root_relative is a function in 2.0.
Apache::server_root_relative
my $conf_dir = Apache::server_root_relative($r->pool, 'conf');
See the Apache::ServerUtil manpage.
The methods from module Apache::File have been either moved to other packages or removed.
Apache::File
open()
close()
See the implementation in the module Apache::compat.
tmpfile()
See File::Temp, or the implementation in the module Apache::compat.
File::Temp
It was removed since Apache 2.0 doesn't have the API for this method anymore.
mtime()
mtime() now belongs to the module Apache::RequestRec.
discard_request_body()
meets_conditions()
set_content_length()
set_etag()
set_last_modified()
update_mtime()
These functions now belong to the module Apache::Response.
Apache::Util
A few Apache::Util functions have changed their interface.
Apache::Util::size_string
Apache::Util::size_string has been replaced with APR::String::format_size, which returns formatted strings of only 4 characters long. See the APR::String manpage.
APR::String::format_size
APR::String
Apache::Util::unescape_uri()
Apache::Util::unescape_uri() is now Apache::unescape_url().
Apache::unescape_url()
Apache::URI
Apache::URI->parse($r, [$uri])
Apache::URI->parse() has been replaced with APR::URI->parse(), which is invoked as:
Apache::URI->parse()
APR::URI->parse()
my $curl = $r->construct_url; APR::URI->parse($r->pool, $curl);
See the APR::URI manpage.
In mod_perl 1.0 the method handlers could be specified by using the ($$) prototype:
($$)
package Bird; @ISA = qw(Eagle); sub handler ($$) { my($class, $r) = @_; ...; }
Starting from Perl version 5.6 the subroutine attributes are used in place of subroutine prototypes:
package Bird; @ISA = qw(Eagle); sub handler : method { my($class, $r) = @_; ...; }
See the attributes manpage.
mod_perl 2.0 doesn't support the ($$) prototypes, mainly because several callbacks in 2.0 have more arguments than $r, so the ($$) prototype doesn't make sense anymore. Therefore if you want your code to work with both mod_perl generations, you should use the subroutine attributes.
$r
Apache::StatINC
Apache::StatINC has been replaced by Apache::Reload.
Apache::Reload
Maintainer is the person(s) you should contact with updates, corrections and patches.
Stas Bekman <stas (at) stason.org>
Only the major authors are listed above. For contributors see the Changes file.
To install mod_perl, copy and paste the appropriate command in to your terminal.
cpanm
cpanm mod_perl
CPAN shell
perl -MCPAN -e shell install mod_perl
For more information on module installation, please visit the detailed CPAN module installation guide.