home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright 1999 by O'Reilly & Associates, Inc.


   Show Contents   Previous Page   Next Page

Chapter 3 - The Apache Module Architecture and API / The Apache Life Cycle
Internal Requests and Subrequests

Although the majority of transactions will pass through each phase of the request processing cycle from beginning to end, this isn't always the case. An error at any of the phases will terminate processing, causing processing to jump immediately to the logging and cleanup phases.

In addition, there are a variety of conditions that can trigger internal requests. An internal request is just like an ordinary request, except that it is generated by Apache itself. An internal request can be explicitly generated by a handler that has decided to return a document other than the one that the browser requested. By calling the internal_redirect() function, the handler tells Apache to stop processing the current request and go process another one.

More commonly, internal requests are generated by Apache's ErrorDocument system, when an error returned by a content handler triggers Apache to fetch and display a custom HTML file or CGI script to help explain to the user what went wrong.

A special case of an internal request is a subrequest, which is commonly used by modules to ask "what if" questions. At any stage of the transaction, a handler can pass a file or URI to the lookup_file() or lookup_uri() functions. Each of these functions creates a request that will appear to handlers just as if it came from a client outside of the server. In the case of lookup_uri(), the URI translate handler is the first to be run. The header parser phase is skipped, and then all other handlers down the request chain are run, stopping just before the content response phase. In the case of lookup_file(), Apache assumes the given file already exists, so URI translation is skipped and the subrequest starts out with the access checker, continuing along the same road as lookup_uri(). After the subrequest is finished, Apache returns the new request record to the caller, which can check for success or failure in the status field. The caller may manually run the subrequest's response phase if desired. In any case, the logging phase will never be run for a subrequest, only the main request itself.

For example, the handler responsible for authorization ordinarily does not have access to the MIME type of the requested file because the MIME type checker phase comes after the authorization phase. In order to implement authorization based on the MIME type of the requested document, the authorization handler could generate a subrequest for the requested file in order to run all the phases up to, but not including, the content generation and logging phases. It can then retrieve the file's MIME type from the subrequest result.

The Environment and Subprocesses

   Show Contents   Go to Top   Previous Page   Next Page

Several of Apache's standard modules use environment variables: mod_cgi sets a number of environment variables to hold information about the HTTP request prior to launching CGI scripts, mod_include uses environment variables in HTML string substitutions, mod_log_config can incorporate the values of environment variables into custom log entries, and mod_access can base its access restriction decisions on the value of environment variables.

Ordinarily, the environment passed to subprocesses is a strictly limited set of variables that contain information about the server and the current request. You can modify this default list using the PassEnv, SetEnv, and UnsetEnv directives all of which are implemented by the mod_env module (compiled in by default). Pass-Env passes an environment variable from the server's environment into that of the subprocess, while SetEnv and UnsetEnv allow you to set or unset an environment variable explicitly. Note that PassEnv and SetEnv are not set until the fixup stage, a rarely used phase that runs just before the response phase. If you need to use such environment variables earlier in the request, the mod_perl equivalents, Perl-PassEnv and PerlSetEnv, will set the variables as soon as possible. These work just like the Apache equivalents, except that the two directives can be placed in <Directory> and <Location> sections, as shown in the following examples:

PerlSetEnv      TMPDIR  /usr/tmp
<Location /stage/upload>
PerlSetEnv      TMPDIR /tmp/staging

The mod_setenvif module (compiled in by default) adds the BrowserMatch and SetEnvIf directives, allowing you to selectively set and unset variables based on attributes of the incoming request.

Apache has a standard way of managing the process environment area. When Apache starts up, it copies certain environment variables from its own environment into an internal table (which variables are inherited in this way can be controlled with the PassEnv and PerlPassEnv directives). Later, modules that need access to the environment get their information from the table rather than reading it directly from the environment area. Not only is this more efficient, but it gives Apache more control over a potentially security-sensitive domain. If a module such as mod_cgi needs to launch a subprocess, it passes the internal environment table to the process rather than using the current system environment.

The Perl and C APIs allow you to examine and set the contents of this environment table. There is also a mechanism for launching and communicating with subprocesses.

We'll now look at the Perl API for installing handlers and manipulating the Apache life cycle.


4 The Apache documentation sometimes refers to handlers as "hooks" or "callbacks," but don't worry, they're all the same thing.

5 Older versions of the mod_perl package had a PerlScript directive, which was later renamed to PerlRequire. The PerlScript directive has been deprecated, but you might still see references to it in old online archives.    Show Contents   Go to Top   Previous Page   Next Page
Copyright 1999 by O'Reilly & Associates, Inc.