Directives that accept zero or one argument are represented as
scalars. For example, CacheNegotiatedDocs is a
directive with no arguments. In Perl, we just assign it an empty
string:
<Perl>
$CacheNegotiatedDocs = '';
</Perl>
Directives that accept a single value are simple to handle. For
example, to configure Apache so that child processes run as user
httpd and group httpd, use:
User = httpd
Group = httpd
What if we don't want user and group definitions to
be hardcoded? Instead, what if we want to define them on the fly
using the user and group with which the server is started? This is
easily done with <Perl>sections:
<Perl>
$User = getpwuid($>) || $>;
$Group = getgrgid($)) || $);
</Perl>
We use the power of the Perl API to retrieve the data on the fly.
$User is set to the name of the effective user ID
with which the server was started or, if the name is not defined, the
numeric user ID. Similarly, $Group is set to
either the symbolic value of the effective group ID or the numeric
group ID.
Notice that we've just taken the Apache directives
and prepended a $, as they represent scalars.
Directives that implement a container block, with beginning and
ending delimiters such as <Location> ...
</Location>, are represented as Perl hashes.
In these hashes, the keys are the arguments of the opening directive,
and the values are the contents of the block. For example:
Alias /private /home/httpd/docs/private
<Location /private>
DirectoryIndex index.html index.htm
AuthType Basic
AuthName "Private Area"
AuthUserFile /home/httpd/docs/private/.htpasswd
Require valid-user
</Location>
These settings tell Apache that URIs starting with
/private are mapped to the physical directory
/home/httpd/docs/private/ and will be processed
according to the following rules:
-
The users are to be authenticated using basic authentication.
-
PrivateArea will be used as the title of the
pop-up box displaying the login and password entry form.
-
Only valid users listed in the password file
/home/httpd/docs/private/.htpasswd and who
provide a valid password may access the resources under
/private/.
-
If the filename is not provided, Apache will attempt to respond with
the index.html or index.htm
directory index file, if found.
Now let's see the equivalent
<Perl>section:
<Perl>
push @Alias, qw(/private /home/httpd/docs/private);
$Location{"/private"} = {
DirectoryIndex => [qw(index.html index.htm)],
AuthType => 'Basic',
AuthName => '"Private Area"',
AuthUserFile => '/home/httpd/docs/private/.htpasswd',
Require => 'valid-user',
};
</Perl>
First, we convert the Alias directive into an
array @Alias. Instead of assigning, however, we
push the values at the end. We do this because it's
possible that we have assigned values earlier, and we
don't want to overwrite them. Alternatively, you may
want to push references to lists, like this:
push @Alias, [qw(/private /home/httpd/docs/private)];
Second, we convert the Location block, using
/private as a key to the hash
%Location and the rest of the block as its value.
When the structures are nested, the normal Perl rules
apply—that is, arrays and hashes turn into references.
Therefore, DirectoryIndex points to an array
reference. As shown earlier, we can always replace this array with a
space-delimited string:
$Location{"/private"} = {
DirectoryIndex => 'index.html index.htm',
...
};
Also notice how we specify the value of the
AuthName attribute:
AuthName => '"Private Area"',
The value is quoted twice because Apache expects a single value for
this argument, and if we write:
AuthName => 'Private Area',
<Perl> will pass two values to Apache,
"Private" and
"Area", and Apache will refuse to
start, with the following complaint:
[Thu May 16 17:01:20 2002] [error] <Perl>: AuthName takes one
argument, The authentication realm (e.g. "Members Only")