WebReference.com - Chapter 4 from The mod_perl Developer's Cookbook, from Sams Publishing (2/6)
[previous] [next] |
mod_perl Developer's Cookbook
4.2. Simulating IfModule
and IfDefine
Directives
You want to know whether a particular Apache module was loaded into the
server configuration, or whether a specific command-line switch was passed to
the server when it was started.
Technique
IfModule
and IfDefine
DirectivesYou want to know whether a particular Apache module was loaded into the server configuration, or whether a specific command-line switch was passed to the server when it was started.
Use the module()
or define()
method from the
Apache
class.
package Cookbook::SSLStatus;
use Apache::URI;
use strict;
# Add a menu item to /perl-status that shows whether this
# server is SSL ready.
# Actually, it just relies on the -DSSL command line switch,
# but since that's the convention...
if (Apache->module('Apache::Status')) {
Apache::Status->menu_item('SSL',
'SSL status',
\&status);
sub status {
my $r = shift;
my $ssl = $r->define('SSL');
my @string = ("Apache was started ",
$ssl ? "with " : "without ",
"-DSSL");
if ($ssl) {
my $uri = Apache::URI->parse($r);
$uri->scheme('https');
my $new_uri = $uri->unparse;
push @string, qq!<br><a href="$new_uri">
Go to this page via a secure connection</a>
!;
}
return \@string;
}
}
1;
Comments
As we alluded to in Recipe 2.16, knowing whether a module has been loaded
into the server is possible using the module()
method. Analogous to the
IfModule
directive, module()
will return true if the passed
argument matches a present Apache C extension module currently present within
the server (whether statically compiled into the httpd
binary or
included with the LoadModule
directive) or a Perl module currently in
%INC
. For Apache C modules, the full name of the module with the
.c
extension is required.
# Test whether mod_dir has been enabled.
return DECLINED if $r->module('mod_dir.c');
Along similar lines, the define()
method offers a hook into Apache's
IfDefine
directive, returning true if a particular -D
command-line switch was passed to httpd
when the server was
started.
The Cookbook::SSLStatus
example package illustrates both of these
methods by hooking into a neat feature of Apache::Status
.
Apache::Status
offers the menu_item()
method as a way to add
custom menu items to the /perl-status
display. When our example code is
configured in httpd.conf
with
PerlModule Apache::Status
PerlModule Cookbook::SSLStatus
and the other Apache::Status
configuration directives listed in
Recipe 1.14, the result is a nice /perl-status?SSL
menu item that shows
whether Apache was started with the ÂDSSL
command-line switch and
offers a secure link to /perl-status
so you can verify the status of
the SSL engine.
As with the module()
call in this example, both module()
and define()
can be called from outside of a request using a direct
call from the Apache
class. This makes them useful for code run during
module initialization or for <Perl>
sections. For instance,
another way of writing the example from Recipe 2.18 would be
<Perl>
$PerlModule = 'Apache::DProf' if Apache->define('PROFILE');
</Perl>
4.3. Accessing ServerRoot
and DocumentRoot
You need to know the
ServerRoot
andDocumentRoot
settings for the server.
Technique
Use the server_root_relative()
and document_root()
methods
from the Apache
class.
sub handler {
my $r = shift;
my $document_root = $r->document_root;
my $server_root = $r->server_root_relative;
my $mimefile = $r->server_root_relative("conf/mime.types");
# Continue along...
}
Comments
Although the ServerRoot
and DocumentRoot
configuration
directives are really directives directly associated with a server, they exist
outside of the Apache server record. Thus, methods for accessing these
directives are not part of the Apache::Server
class.
At first, the name may appear slightly misleading, because the
server_root_relative()
method returns the value set by the core
ServerRoot
directive, which is always an absolute path in your
filesystem. However, the server_root_relative()
method is most useful
for resolving default configuration files, such as conf/mime.types
, to
their full filenames.
The "relative" part comes from the ability of server_root_relative()
to resolve a filename relative to ServerRoot
into its complete path on
disk. For instance, in the first part of the solution code,
$r->server_root_relative()
might return /usr/local/apache/
.
Using it to resolve conf/mime.types
, as in the second part of the
example, would return /usr/local/apache/conf/mime.types
. A nice feature
of server_root_relative()
is that if the argument happens to already
contain ServerRoot
, server_root_relative()
is intelligent
enough to determine this and returns the proper filename. Note that in either
case, ServerRoot
is merely prependedÂno checking is done to determine
whether the resulting file actually exists.
Because server_root_relative()
is a fundamental property of the
Apache server, determining the value of ServerRoot
at startup is
possible. For instance, to prevent any additional hardcoding, the
Apache::RegistryLoader
code from the startup.pl
in Recipe 2.5
could be rewritten as
foreach my $file ($dh->read) {
next unless $file =~ m/\.(pl|cgi)$/;
$rl->handler("/perl-bin/$file",
Apache->server_root_relative("perl-bin/$file"));
}
to allow for maximum portability.
The document_root()
method similarly returns the current value of
the DocumentRoot
configuration directive. However, unlike the value of
ServerRoot
, which is read-only, document_root()
can be used
(with due caution) to change the value of DocumentRoot
on-the-fly.
package Cookbook::Userdir;
# A simple PerlTransHandler that mimics mod_userdir.
use Apache::Constants qw(OK DECLINED);
use strict;
sub handler {
my $r = shift;
# Capture the old DocumentRoot setting.
my $old_docroot = $r->document_root;
# We have to get a bit funky here to help out mod_dir.
if (my ($user, $path) = $r->uri =~ m!^/~ # Starts with a slash-tilde
([^/]+) # One or more characters that
# are not a slash
/? # Zero or one trailing slashes
(.*) # All the rest
!x) {
# Set DocumentRoot to the new value.
$r->document_root("/home/$user/public_html");
# Set the URI to the path without the username.
$r->uri("/$path");
# Remember to set the original DocumentRoot back.
# Here we use a closure.
$r->push_handlers(PerlCleanupHandler =>
sub {
shift->document_root($old_docroot);
return OK;
}
);
}
return DECLINED;
}
1;
Although we could have just written a PerlTransHandler
that patched
$r->filename
instead, document_root()
allows us to take
advantage of things such as configured Alias
directives and also makes
sure that everything is neat and tidy (like setting
$ENV{DOCUMENT_ROOT}
). As mentioned in Recipe 4.1, when manipulating
server attributes at runtime, it is best to be sure that the original values are
restored, because changes to server attributes will persist for the lifetime of
the child process.
[previous] [next] |
Copyright © Pearson Education and
Created: March 18, 2002
Revised: March 18, 2002
URL: https://webreference.com/programming/perl/cookbook/chap4/2.html