- NAME
- Synopsis
- Description
- API
  - server
- @PerlConfig and $PerlConfig
- Configuration Variables
  - $Apache2::PerlSections::Save
- PerlSections Dumping
  - Apache2::PerlSections->dump
  - Apache2::PerlSections->store
- Advanced API
- Verifying <Perl> Sections
- Bugs
  - <Perl> directive missing closing '>'
  - <Perl>[...]> was not closed.
- See Also
- Copyright
- Authors

# 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.

# 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.