Help-Site Computer Manuals
Software
Hardware
Programming
Networking
  Algorithms & Data Structures   Programming Languages   Revision Control
  Protocols
  Cameras   Computers   Displays   Keyboards & Mice   Motherboards   Networking   Printers & Scanners   Storage
  Windows   Linux & Unix   Mac

Apache2::PerlSections
write Apache configuration files in Perl

Apache2::PerlSections - write Apache configuration files in Perl


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|docs::2.0::api::Apache2::ServerRec )
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|docs::2.0::api::Apache2::RequestUtil/C_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|docs::2.0::api::Apache2::Status and Apache2::PerlSections->dump|/C_Apache2__PerlSections_E_gt_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|docs::2.0::api::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|docs::2.0::api::APR::Table)
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.


Copyright

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.

Programminig
Wy
Wy
yW
Wy
Programming
Wy
Wy
Wy
Wy