Show Contents Previous Page Next Page Chapter 8 - Customizing the Apache Configuration Process In this section...
We've just seen how you can configure Perl modules using the Apache configuration mechanism. Now we turn it around to show you how to configure Apache from within Perl. Instead of configuring Apache by hand (editing a set of configuration files), the Perl API allows you to write a set of Perl statements to dynamically configure Apache at runtime. This gives you limitless flexibility. For example, you can create complex configurations involving hundreds of virtual hosts without manually typing hundreds of <VirtualHost> sections into httpd.conf. Or you can write a master configuration file that will work without modification on any machine in a "server farm." You could even look up configuration information at runtime from a relational database. The key to Perl-based server configuration is the <Perl>
directive. Unlike the other directives defined by When Apache hits a Perl section during startup time, it passes everything
within the section to User www you can write this: <Perl> $User = 'www'; </Perl> This doesn't look like much of a win until you consider that you can set this global using any arbitrary Perl expression, for example: <Perl> my $hostname = `hostname`; $User = 'www' if $hostname =~ /^papa-bear/; $User = 'httpd' if $hostname =~ /^momma-bear/; $User = 'nobody' if $hostname =~ /^goldilocks/; </Perl> The Perl global that you set must match the spelling of the corresponding Apache directive. Globals that do not match known Apache directives are silently ignored. Capitalization is not currently significant. In addition to single-valued directives such as User, Group, and ServerRoot, you can use <Perl> sections to set multivalued directives such as DirectoryIndex and AddType. You can also configure multipart sections such as <Directory> and <VirtualHost>. Depending on the directive, the Perl global you need to set may be a scalar, an array, or a hash. To figure out what type of Perl variable to use, follow these rules:
There are few examples of configuration directives that take no arguments.
The only one that occurs in the standard Apache modules is CacheNegotiatedDocs,
which is part of mod_ negotiation. To create a nonargument directive,
set the corresponding scalar variable to the empty string $CacheNegotiatedDocs = '';
This is probably the most common case. Set the corresponding global to the value of your choice. $Port = 8080;
These include directives such as DirectoryIndex and AddType. Create a global array with the name of the directive and set it to the list of desired arguments. @DirectoryIndex = map { "index.$_" } qw(html htm shtml cgi); An alternative to this is to create a scalar variable containing the usual value of the directive as a string, for example: $DirectoryIndex = "index.html index.htm index.shtml index.cgi";
If a directive is repeated multiple times with different arguments each time, you can represent it as an array of arrays. This example using the AddIcon directive shows how: @AddIcon = ( [ '/icons/compressed.gif' => qw(.Z .z .gz .tgz .zip) ], [ '/icons/layout.gif' => qw(.html .shtml .htm .pdf) ], );
Configuration sections like <VirtualHost> and <Directory> are mapped onto Perl hashes. Use the directive's argument (the hostname, directory, or URI) as the hash key, and make the value stored at this key an anonymous hash containing the desired directive/value pairs. This is easier to see than to describe. Consider the following virtual host section: <VirtualHost 192.168.2.5:80> ServerName www.fishfries.org DocumentRoot /home/httpd/fishfries/htdocs ErrorLog /home/httpd/fishfries/logs/error.log TransferLog /home/httpd/fishfries/logs/access.log ServerAdmin webmaster@fishfries.org </Virtual> You can represent this in a <Perl> section by the following code: $VirtualHost{'192.168.2.5:80'} = { ServerName => 'www.fishfries.org', DocumentRoot => '/home/httpd/fishfries/htdocs', ErrorLog => '/home/httpd/fishfries/logs/error.log', TransferLog => '/home/httpd/fishfries/logs/access.log', ServerAdmin => 'webmaster@fishfries.org', }; There is no special Perl variable which maps to the <IfModule> directive container; however, the Apache module method will provide you with this functionality. if(Apache->module("mod_ssl.c")) { push @Include, "ssl.conf"; } The Apache define() method can be used to implement an <IfDefine> container, as follows: if(Apache->define("MOD_SSL")) { push @Include, "ssl.conf"; } Certain configuration blocks may require directives to be in a particular
order. As you probably know, Perl does not maintain hash values in any predictable
order. Should you need to preserve order with hashes inside <Perl>
sections, simply install Gurusamy Sarathy's Tie::IxHash module from
CPAN. Once installed,
The Apache named virtual host mechanism provides a way to configure virtual hosts using the same IP address. NameVirtualHost 192.168.2.5 <VirtualHost 192.168.2.5> ServerName one.fish.net ServerAdmin webmaster@one.fish.net </VirtualHost> <VirtualHost 192.168.2.5> ServerName red.fish.net ServerAdmin webmaster@red.fish.net </VirtualHost> In this case, the $VirtualHost{'192.168.2.5'} = [ { ServerName => 'one.fish.net', ... ServerAdmin => 'webmaster@one.fish.net', }, { ServerName => 'red.fish.net', ... ServerAdmin => 'webmaster@red.fish.net', }, ];
Nested block sections are mapped onto anonymous hashes, much like main sections. For example, to put two <Directory> sections inside the virtual host of the previous example, you can use this code: <Perl> my $root = '/home/httpd/fishfries'; $VirtualHost{'192.168.2.5:80'} = { ServerName => 'www.fishfries.org', DocumentRoot => "$root/htdocs", ErrorLog => "$root/logs/error.log", TransferLog => "$root/logs/access.log", ServerAdmin => 'webmaster@fishfries.org', Directory => { "$root/htdocs" => { Options => 'Indexes FollowSymlinks', AllowOverride => 'Options Indexes Limit FileInfo', Order => 'deny,allow', Deny => 'from all', Allow => 'from fishfries.org', }, "$root/cgi-bin" => { AllowOverride => 'None', Options => 'ExecCGI', SetHandler => 'cgi-script', }, }, }; </Perl> Notice that all the usual Perlisms, such as interpolation of the Options => 'Indexes FollowSymlinks', The alternative would be to use an anonymous array for the directive's arguments, as in: Options => ['Indexes','FollowSymlinks'], Both methods work. The only gotcha is that you must always be sure of what
is an argument list and what isn't. In the Options directive, "Indexes"
and "FollowSymlinks" are distinct arguments and can be represented as an anonymous
array. In the Order directive, the string <Perl> sections are available if you built and installed
Copyright © 1999 by O'Reilly & Associates, Inc. |
HIVE: All information for read only. Please respect copyright! |