=head1 NAME
Apache2::PerlSections - write Apache configuration files in Perl
=head1 Synopsis
@PerlModule = qw(Mail::Send Devel::Peek);
#run the server as whoever starts it
$User = getpwuid(>) || >;
$Group = getgrgid()) || );
$ServerAdmin = $User;
=head1 Description
With CPerlE>...C/PerlE> sections, it is possible
to configure your server entirely in Perl.
CPerlE> sections can contain I and as much Perl code as
you wish. These sections are compiled into a special package whose
symbol table mod_perl can then walk and grind the names and values of
Perl variables/structures through the Apache core configuration gears.
Block sections such as CLocationE>..C/LocationE>
are represented in a C<%Location> hash, e.g.:
$Location{"/~dougm/"} = {
AuthUserFile => '/tmp/htpasswd',
AuthType => 'Basic',
AuthName => 'test',
DirectoryIndex => [qw(index.html index.htm)],
Limit => {
"GET POST" => {
require => 'user dougm',
}
},
};
If an Apache directive can take two or three arguments you may push
strings (the lowest number of arguments will be shifted off the
C<@list>) or use an array reference to handle any number greater than
the minimum for that directive:
push @Redirect, "/foo", "http://www.foo.com/";
push @Redirect, "/imdb", "http://www.imdb.com/";
push @Redirect, [qw(temp "/here" "http://www.there.com")];
Other section counterparts include C<%VirtualHost>, C<%Directory> and
C<%Files>.
To pass all environment variables to the children with a single
configuration directive, rather than listing each one via C
or C, a CPerlE> section could read in a file and:
push @PerlPassEnv, [$key => $val];
or
Apache2->httpd_conf("PerlPassEnv $key $val");
These are somewhat simple examples, but they should give you the basic
idea. You can mix in any Perl code you desire. See I
and I in the mod_perl distribution for more
examples.
Assume that you have a cluster of machines with similar configurations
and only small distinctions between them: ideally you would want to
maintain a single configuration file, but because the configurations
aren't I the same (e.g. the C directive) it's not
quite that simple.
CPerlE> sections come to rescue. Now you have a single
configuration file and the full power of Perl to tweak the local
configuration. For example to solve the problem of the C
directive you might have this CPerlE> section:
$ServerName = `hostname`;
For example if you want to allow personal directories on all machines
except the ones whose names start with I:
$ServerName = `hostname`;
if ($ServerName !~ /^secure/) {
$UserDir = "public.html";
}
else {
$UserDir = "DISABLED";
}
=head1 API
C provides the following functions and/or methods:
=head2 C
Get the current server's object for the EPerlE section
$s = Apache2::PerlSections->server();
=over 4
=item obj: C (class name)
=item ret: C<$s>
( C> )
=item since: 2.0.03
=back
=head1 C<@PerlConfig> and C<$PerlConfig>
This array and scalar can be used to introduce literal configuration
into the apache configuration. For example:
push @PerlConfig, 'Alias /foo /bar';
Or:
$PerlConfig .= "Alias /foo /bar\n";
See also
Cadd_config|docs::2.0::api::Apache2::RequestUtil/C_add_config_>>
=head1 Configuration Variables
There are a few variables that can be set to change the default
behaviour of CPerlE> sections.
=head2 C<$Apache2::PerlSections::Save>
Each CPerlE> section is evaluated in its unique namespace,
by default residing in a sub-namespace of C,
therefore any local variables will end up in that namespace. For
example if a CPerlE> section happened to be in file
F starting on line 20, the namespace:
C will be used. Now if
it had:
$foo = 5;
my $bar = 6;
$My::tar = 7;
The local global variable C<$foo> becomes
C<$Apache2::ReadConfig::tmp::httpd_conf::line_20::foo>, the other
variable remain where they are.
By default, the namespace in which CPerlE> sections are
evaluated is cleared after each block closes. In our example nuking
C<$Apache2::ReadConfig::tmp::httpd_conf::line_20::foo>, leaving the
rest untouched.
By setting C<$Apache2::PerlSections::Save> to a true value, the content
of those namespaces will be preserved and will be available for
inspection by C> and
Cdump|/C_Apache2__PerlSections_E_gt_dump_>>
In our example C<$Apache2::ReadConfig::tmp::httpd_conf::line_20::foo>
will still be accessible from other perl code, after the
CPerlE> section was parsed.
=head1 PerlSections Dumping
=head2 Cdump>
This method will dump out all the configuration variables mod_perl
will be feeding to the apache config gears. The output is suitable to
read back in via C.
my $dump = Apache2::PerlSections->dump;
=over 4
=item ret: C<$dump> ( string / C )
A string dump of all the Perl code encountered in EPerlE blocks,
suitable to be read back via C
=back
For example:
$Apache2::PerlSections::Save = 1;
$Listen = 8529;
$Location{"/perl"} = {
SetHandler => "perl-script",
PerlHandler => "ModPerl::Registry",
Options => "ExecCGI",
};
@DirectoryIndex = qw(index.htm index.html);
$VirtualHost{"www.foo.com"} = {
DocumentRoot => "/tmp/docs",
ErrorLog => "/dev/null",
Location => {
"/" => {
Allowoverride => 'All',
Order => 'deny,allow',
Deny => 'from all',
Allow => 'from foo.com',
},
},
};
print Apache2::PerlSections->dump;
This will print something like this:
$Listen = 8529;
@DirectoryIndex = (
'index.htm',
'index.html'
);
$Location{'/perl'} = (
PerlHandler => 'Apache2::Registry',
SetHandler => 'perl-script',
Options => 'ExecCGI'
);
$VirtualHost{'www.foo.com'} = (
Location => {
'/' => {
Deny => 'from all',
Order => 'deny,allow',
Allow => 'from foo.com',
Allowoverride => 'All'
}
},
DocumentRoot => '/tmp/docs',
ErrorLog => '/dev/null'
);
1;
__END__
It is important to put the call to C in it's own CPerlE>
section, otherwise the content of the current CPerlE> section
will not be dumped.
=head2 Cstore>
This method will call the C method, writing the output
to a file, suitable to be pulled in via C or C.
Apache2::PerlSections->store($filename);
=over 4
=item arg1: C<$filename> (string)
The filename to save the dump output to
=item ret: no return value
=back
=head1 Advanced API
mod_perl 2.0 now introduces the same general concept of handlers to
CPerlE> sections. Apache2::PerlSections simply being the
default handler for them.
To specify a different handler for a given perl section, an extra
handler argument must be given to the section:
$foo = 1;
$bar = 2;
And in My/PerlSection/Handler.pm:
sub My::Handler::handler : handler {
my ($self, $parms, $args) = @_;
#do your thing!
}
So, when that given CPerlE> block in encountered, the code
within will first be evaluated, then the handler routine will be
invoked with 3 arguments:
=over
=item arg1: C<$self>
self-explanatory
=item arg2: C<$parms>
( C> )
C<$parms> is specific for the current Container, for example, you
might want to call C<$parms-Eserver()> to get the current server.
=item arg3: C<$args>
( C>)
the table object of the section arguments. The 2 guaranteed ones will
be:
$args->{'handler'} = 'My::PerlSection::Handler';
$args->{'package'} = 'Apache2::ReadConfig';
Other C pairs given on the CPerlE> line will
also be included.
=back
At this point, it's up to the handler routing to inspect the namespace
of the C<$args>-E{'package'} and chooses what to do.
The most likely thing to do is to feed configuration data back into
apache. To do that, use Apache2::Server-Eadd_config("directive"),
for example:
$parms->server->add_config("Alias /foo /bar");
Would create a new alias. The source code of C
is a good place to look for a practical example.
=head1 Verifying CPerlE> Sections
If the CPerlE> sections include no code requiring a running
mod_perl, it is possible to check those from the command line. But the
following trick should be used:
# file: httpd.conf
#!perl
# ... code here ...
__END__
Now you can run:
% perl -c httpd.conf
=head1 Bugs
=head2 EPerlE directive missing closing 'E'
httpd-2.0.47 had a bug in the configuration parser which caused the
startup failure with the following error:
Starting httpd:
Syntax error on line ... of /etc/httpd/conf/httpd.conf:
directive missing closing '>' [FAILED]
This has been fixed in httpd-2.0.48. If you can't upgrade to this or a
higher version, please add a space before the closing 'E' of the
opening tag as a workaround. So if you had:
# some code
change it to be:
# some code
=head2 EPerlE[...]E was not closed.
On encountering a one-line EPerlE block,
httpd's configuration parser will cause a startup
failure with an error similar to this one:
Starting httpd:
Syntax error on line ... of /etc/httpd/conf/httpd.conf:
use> was not closed.
If you have written a simple one-line EPerlE
section like this one :
use Apache::DBI;
change it to be:
use Apache::DBI;
This is caused by a limitation of httpd's configuration
parser and is not likely to be changed to allow one-line
block like the example above. Use multi-line blocks instead.
=head1 See Also
L.
=head1 Copyright
mod_perl 2.0 and its core modules are copyrighted under
The Apache Software License, Version 2.0.
=head1 Authors
L.
=cut