NAME
Plack::Handler::Apache2 - Apache 2.0 mod_perl handler to run PSGI application
SYNOPSIS
# in your httpd.conf
<Location />
SetHandler perl-script
PerlResponseHandler Plack::Handler::Apache2
PerlSetVar psgi_app /path/to/app.psgi
</Location>
# Optionally preload your apps in startup
PerlPostConfigRequire /etc/httpd/startup.pl
See "STARTUP FILE" for more details on writing a startup.pl
.
DESCRIPTION
This is a mod_perl handler module to run any PSGI application with mod_perl on Apache 2.x.
If you want to run PSGI applications behind Apache instead of using mod_perl, see Plack::Handler::FCGI to run with FastCGI, or use standalone HTTP servers such as Starman or Starlet proxied with mod_proxy.
CREATING CUSTOM HANDLER
If you want to create a custom handler that loads or creates PSGI applications using other means than loading from .psgi
files, you can create your own handler class and use call_app
class method to run your application.
package
My::ModPerl::Handler;
sub
get_app {
# magic!
}
sub
handler {
my
$r
=
shift
;
my
$app
= get_app();
Plack::Handler::Apache2->call_app(
$r
,
$app
);
}
STARTUP FILE
Here is an example startup.pl
to preload PSGI applications:
#!/usr/bin/env perl
use
strict;
use
warnings;
use
Apache2::ServerUtil ();
BEGIN {
return
unless
Apache2::ServerUtil::restart_count() > 1;
lib->
import
(
'/path/to/my/perl/libs'
);
my
@psgis
= (
'/path/to/app1.psgi'
,
'/path/to/app2.psgi'
);
foreach
my
$psgi
(
@psgis
) {
Plack::Handler::Apache2->preload(
$psgi
);
}
}
1;
# file must return true!
See http://perl.apache.org/docs/2.0/user/handlers/server.html#Startup_File for general information on the startup.pl
file for preloading perl modules and your apps.
Some things to keep in mind when writing this file:
multiple init phases
You have to check that "restart_count" in Apache2::ServerUtil is
> 1
, otherwise your app will load twice and the env vars you set with PerlSetEnv will not be available when your app is loading the first time.Use the example above as a template.
@INC
The
startup.pl
file is a good place to add entries to your@INC
. Use lib to add entries, they can be in your app or.psgi
as well, but if your modules are in a local::lib or some such, you will need to add the path for anything to load.Alternately, if you follow the example above, you can use:
PerlSetEnv PERL5LIB /some/path
or
PerlSwitches -I/some/path
in your
httpd.conf
, which will also work.loading errors
Any exceptions thrown in your
startup.pl
will stop Apache from starting at all.You probably don't want a stray syntax error to bring your whole server down in a shared or development environment, in which case it's a good idea to wrap the "preload" call in an eval, using something like this:
require
Plack::Handler::Apache2;
my
@psgis
= (
'/path/to/app1.psgi'
,
'/path/to/app2.psgi'
);
foreach
my
$psgi
(
@psgis
) {
eval
{
Plack::Handler::Apache2->preload(
$psgi
); 1;
} or
do
{
my
$error
= $@ ||
'Unknown Error'
;
# STDERR goes to the error_log
print
STDERR
"Failed to load psgi '$psgi': $error\n"
;
};
}
dynamically loaded modules
Some modules load their dependencies at runtime via e.g. Class::Load. These modules will not get preloaded into your parent process by just including the app/module you are using.
As an optimization, you can dump
%INC
from a request to see if you are using any such modules and preload them in yourstartup.pl
.Another method is dumping the difference between the
%INC
on process start and process exit. You can use something like this to accomplish this:my
$start_inc
= {
%INC
};
END {
my
@m
;
foreach
my
$m
(
keys
%INC
) {
push
@m
,
$m
unless
exists
$start_inc
->{
$m
};
}
if
(
@m
) {
# STDERR goes to the error_log
print
STDERR
"The following modules need to be preloaded:\n"
;
print
STDERR
"$_\n"
for
@m
;
}
}
AUTHOR
Tatsuhiko Miyagawa
CONTRIBUTORS
Paul Driver
Ævar Arnfjörð Bjarmason
Rafael Kitover