Apache2::PerlSections.3pm

Langue: en

Version: 2007-11-12 (fedora - 01/12/10)

Section: 3 (Bibliothèques de fonctions)

NAME

Apache2::PerlSections - write Apache configuration files in Perl

Synopsis

   <Perl>
   @PerlModule = qw(Mail::Send Devel::Peek);
   
   #run the server as whoever starts it
   $User  = getpwuid(>) || >;
   $Group = getgrgid()) || );
   
   $ServerAdmin = $User;
   
   </Perl>
 
 

Description

With "<Perl>"..."</Perl>" sections, it is possible to configure your server entirely in Perl.

"<Perl>" sections can contain any 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 "<Location>".."</Location>" are represented in a %Location hash, e.g.:

   <Perl>
   $Location{"/~dougm/"} = {
     AuthUserFile   => '/tmp/htpasswd',
     AuthType       => 'Basic',
     AuthName       => 'test',
     DirectoryIndex => [qw(index.html index.htm)],
     Limit          => {
         "GET POST"    => {
             require => 'user dougm',
         }
     },
   };
   </Perl>
 
 

If an Apache directive can take two or three arguments you may push strings (the lowest number of arguments will be shifted off the @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 %VirtualHost, %Directory and %Files.

To pass all environment variables to the children with a single configuration directive, rather than listing each one via "PassEnv" or "PerlPassEnv", a "<Perl>" 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 eg/httpd.conf.pl and eg/perl_sections.txt 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 exactly the same (e.g. the "ServerName" directive) it's not quite that simple.

"<Perl>" 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 "ServerName" directive you might have this "<Perl>" section:

   <Perl>
   $ServerName = `hostname`;
   </Perl>
 
 

For example if you want to allow personal directories on all machines except the ones whose names start with secure:

   <Perl>
   $ServerName = `hostname`;
   if ($ServerName !~ /^secure/) {
       $UserDir = "public.html";
   }
   else {
       $UserDir = "DISABLED";
   }
   </Perl>
 
 

API

"Apache2::PerlSections" provides the following functions and/or methods:

server

Get the current server's object for the <Perl> section
   <Perl>
     $s = Apache2::PerlSections->server();
   </Perl>
 
 
obj: Apache2::PerlSections (class name)
ret: $s ( Apache2::ServerRec object )
since: 2.0.03

@PerlConfig and $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 "$r->add_config"

Configuration Variables

There are a few variables that can be set to change the default behaviour of "<Perl>" sections.

$Apache2::PerlSections::Save

Each "<Perl>" section is evaluated in its unique namespace, by default residing in a sub-namespace of "Apache2::ReadConfig::", therefore any local variables will end up in that namespace. For example if a "<Perl>" section happened to be in file /tmp/httpd.conf starting on line 20, the namespace: "Apache2::ReadConfig::tmp::httpd_conf::line_20" will be used. Now if it had:
   <Perl>
     $foo     = 5;
     my $bar  = 6;
     $My::tar = 7;
   </Perl>
 
 

The local global variable $foo becomes $Apache2::ReadConfig::tmp::httpd_conf::line_20::foo, the other variable remain where they are.

By default, the namespace in which "<Perl>" sections are evaluated is cleared after each block closes. In our example nuking $Apache2::ReadConfig::tmp::httpd_conf::line_20::foo, leaving the rest untouched.

By setting $Apache2::PerlSections::Save to a true value, the content of those namespaces will be preserved and will be available for inspection by "Apache2::Status" and "Apache2::PerlSections->dump" In our example $Apache2::ReadConfig::tmp::httpd_conf::line_20::foo will still be accessible from other perl code, after the "<Perl>" section was parsed.

PerlSections Dumping

Apache2::PerlSections->dump

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 "eval".
   my $dump = Apache2::PerlSections->dump;
 
 
ret: $dump ( string / undef )
A string dump of all the Perl code encountered in <Perl> blocks, suitable to be read back via "eval"

For example:

   <Perl>
   
   $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',
        },
      },
   };
   </Perl>
   
   <Perl>
   print Apache2::PerlSections->dump;
   </Perl>
 
 

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 "dump" in it's own "<Perl>" section, otherwise the content of the current "<Perl>" section will not be dumped.

Apache2::PerlSections->store

This method will call the "dump" method, writing the output to a file, suitable to be pulled in via "require" or "do".
   Apache2::PerlSections->store($filename);
 
 
arg1: $filename (string)
The filename to save the dump output to
ret: no return value

Advanced API

mod_perl 2.0 now introduces the same general concept of handlers to "<Perl>" 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:

   <Perl handler="My::PerlSection::Handler" somearg="test1">
     $foo = 1;
     $bar = 2;
   </Perl>
 
 

And in My/PerlSection/Handler.pm:

   sub My::Handler::handler : handler {
       my ($self, $parms, $args) = @_;
       #do your thing!
   }
 
 

So, when that given "<Perl>" block in encountered, the code within will first be evaluated, then the handler routine will be invoked with 3 arguments:

arg1: $self
self-explanatory
arg2: $parms ( Apache2::CmdParms )
$parms is specific for the current Container, for example, you might want to call "$parms->server()" to get the current server.
arg3: $args ( APR::Table object)
the table object of the section arguments. The 2 guaranteed ones will be:
   $args->{'handler'} = 'My::PerlSection::Handler';
   $args->{'package'} = 'Apache2::ReadConfig';
 
 

Other "name="value"" pairs given on the "<Perl>" line will also be included.

At this point, it's up to the handler routing to inspect the namespace of the $args->{'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->add_config(``directive''), for example:

   $parms->server->add_config("Alias /foo /bar");
 
 

Would create a new alias. The source code of "Apache2::PerlSections" is a good place to look for a practical example.

Verifying <Perl> Sections

If the "<Perl>" 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>
   #!perl
   
   # ... code here ...
   
   __END__
   </Perl>
 
 

Now you can run:

   % perl -c httpd.conf
 
 

Bugs

<Perl> directive missing closing '>'

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:
   <Perl> 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 '>' of the opening tag as a workaround. So if you had:

   <Perl>
   # some code
   </Perl>
 
 

change it to be:

   <Perl >
   # some code
   </Perl>
 
 

<Perl>[...]> was not closed.

On encountering a one-line <Perl> 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:
   <Perl>use> was not closed.
 
 

If you have written a simple one-line <Perl> section like this one :

   <Perl>use Apache::DBI;</Perl>
 
 

change it to be:

    <Perl>
    use Apache::DBI;
    </Perl>
 
 

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.

See Also

mod_perl 2.0 documentation. mod_perl 2.0 and its core modules are copyrighted under The Apache Software License, Version 2.0.

Authors

The mod_perl development team and numerous contributors.