WebReference.com - Chapter 4 from The mod_perl Developer's Cookbook, from Sams Publishing (2/6) | WebReference

WebReference.com - Chapter 4 from The mod_perl Developer's Cookbook, from Sams Publishing (2/6)

To page 1current pageTo page 3To page 4To page 5To page 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

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 and DocumentRoot 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.


To page 1current pageTo page 3To page 4To page 5To page 6
[previous] [next]

Copyright © Pearson Education and
Created: March 18, 2002
Revised: March 18, 2002


URL: http://webreference.com/programming/perl/cookbook/chap4/2.html