=head1 NAME

Apache2::PerlSections - write Apache configuration files in Perl





=head1 Synopsis

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






=head1 Description

With C<E<lt>PerlE<gt>>...C<E<lt>/PerlE<gt>> sections, it is possible
to configure your server entirely in Perl.

C<E<lt>PerlE<gt>> sections can contain I<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 C<E<lt>LocationE<gt>>..C<E<lt>/LocationE<gt>>
are represented in a C<%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
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<PassEnv>
or C<PerlPassEnv>, a C<E<lt>PerlE<gt>> 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<eg/httpd.conf.pl>
and I<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 I<exactly> the same (e.g. the C<ServerName> directive) it's not
quite that simple.

C<E<lt>PerlE<gt>> 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<ServerName>
directive you might have this C<E<lt>PerlE<gt>> section:

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

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

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





=head1 API

C<Apache2::PerlSections> provides the following functions and/or methods:


=head2 C<server>

Get the current server's object for the E<lt>PerlE<gt> section

  <Perl>
    $s = Apache2::PerlSections->server();
  </Perl>

=over 4

=item obj: C<Apache2::PerlSections> (class name)

=item ret: C<$s>
( C<L<Apache2::ServerRec object|docs::2.0::api::Apache2::ServerRec>> )

=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
C<L<$r-E<gt>add_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 C<E<lt>PerlE<gt>> sections.





=head2 C<$Apache2::PerlSections::Save>

Each C<E<lt>PerlE<gt>> section is evaluated in its unique namespace,
by default residing in a sub-namespace of C<Apache2::ReadConfig::>,
therefore any local variables will end up in that namespace. For
example if a C<E<lt>PerlE<gt>> section happened to be in file
F</tmp/httpd.conf> starting on line 20, the namespace:
C<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 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 C<E<lt>PerlE<gt>> 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<L<Apache2::Status|docs::2.0::api::Apache2::Status>> and
C<L<Apache2::PerlSections-E<gt>dump|/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
C<E<lt>PerlE<gt>> section was parsed.





=head1 PerlSections Dumping



=head2 C<Apache2::PerlSections-E<gt>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 C<eval>.

  my $dump = Apache2::PerlSections->dump;

=over 4

=item ret: C<$dump> ( string / C<undef> )

A string dump of all the Perl code encountered in E<lt>PerlE<gt> blocks,
suitable to be read back via C<eval>

=back

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 C<dump> in it's own C<E<lt>PerlE<gt>>
section, otherwise the content of the current C<E<lt>PerlE<gt>> section
will not be dumped.





=head2 C<Apache2::PerlSections-E<gt>store>

This method will call the C<dump> method, writing the output
to a file, suitable to be pulled in via C<require> or C<do>.

  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
C<E<lt>PerlE<gt>> 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 C<E<lt>PerlE<gt>> 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<L<Apache2::CmdParms|docs::2.0::api::Apache2::CmdParms>> )

C<$parms> is specific for the current Container, for example, you
might want to call C<$parms-E<gt>server()> to get the current server.

=item arg3: C<$args>
( C<L<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 C<name="value"> pairs given on the C<E<lt>PerlE<gt>> 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<gt>{'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-E<gt>add_config("directive"),
for example:

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

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



=head1 Verifying C<E<lt>PerlE<gt>> Sections

If the C<E<lt>PerlE<gt>> 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





=head1 Bugs




=head2 E<lt>PerlE<gt> directive missing closing 'E<gt>'

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

  <Perl>
  # some code
  </Perl>

change it to be:

  <Perl >
  # some code
  </Perl>





=head2 E<lt>PerlE<gt>[...]E<gt> was not closed.

On encountering a one-line E<lt>PerlE<gt> 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 E<lt>PerlE<gt>
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.




=head1 See Also

L<mod_perl 2.0 documentation|docs::2.0::index>.






=head1 Copyright

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




=head1 Authors

L<The mod_perl development team and numerous
contributors|about::contributors::people>.

=cut

