Apache The Definitive Guide, 3rd EditionApache: The Definitive GuideSearch this book

Chapter 21. Writing Apache Modules

Contents:

Overview
Status Codes
The Module Structure
A Complete Example
General Hints
Porting to Apache 2.0

One of the great things about Apache is that if you don't like what it does, you can change it. Now, this is actually true for any package with source code available, but Apache makes this easier. It has a generalized interface to modules that extends the functionality of the base package. In fact, when you download Apache, you get far more than just the base package, which is barely capable of serving files at all. You get all the modules the Apache Group considers vital to a web server. You also get modules that are useful enough to most people to be worth the effort of the Group to maintain them. In this chapter, we explore the intricacies of programming modules for Apache.[74] We expect you to be thoroughly conversant with C and Unix (or Win32), because we are not going to explain anything about them. Refer to Chapter 20 or your Unix/Win32 manuals for information about functions used in the examples. We start out by explaining how to write a module for both Apache 1.3 and 2.0. We also explain how to port a 1.3 module to Apache v2.0.

[74]For more on Apache modules, see Writing Apache Modules with Perl and C, by Lincoln Stein and Doug MacEachern (O'Reilly, 1999).

21.1. Overview

Perhaps the most important part of an Apache module is the module structure. This is defined in http_config.h, so all modules should start (apart from copyright notices, etc.) with the following lines:

#include "httpd.h"
#include "http_config.h"

Note that httpd.h is required for all Apache source code.

What is the module structure for? Simple: it provides the glue between the Apache core and the module's code. It contains pointers (to functions, lists, and so on) that are used by components of the core at the correct moments. The core knows about the various module structures because they are listed in modules.c, which is generated by the Configure script from the Configuration file.[75]

[75]This means, of course, that one should not edit modules.c by hand. Rather, the Configuration file should be edited; see Chapter 1.

Traditionally, each module ends with its module structure. Here is a particularly trivial example, from mod_asis.c (1.3):

module asis_module = {
   STANDARD_MODULE_STUFF,
   NULL,                          /* initializer */
   NULL,                          /* create per-directory config structure */
   NULL,                          /* merge per-directory config structures */
   NULL,                          /* create per-server config structure */
   NULL,                          /* merge per-server config structures */
   NULL,                          /* command table */
   asis_handlers,                 /* handlers */
   NULL,                          /* translate_handler */
   NULL,                          /* check_user_id */
   NULL,                          /* check auth */
   NULL,                          /* check access */
   NULL,                          /* type_checker */
   NULL,                          /* prerun fixups */
   NULL                           /* logger */
   NULL,                          /* header parser */
   NULL,                          /* child_init */
   NULL,                          /* child_exit */
   NULL                           /* post read request */
};

The first entry, STANDARD_MODULE_STUFF, must appear in all module structures. It initializes some structure elements that the core uses to manage modules. Currently, these are the API version number,[76] the index of the module in various vectors, the name of the module (actually, its filename), and a pointer to the next module structure in a linked list of all modules.[77]

[76]This is used, in theory, to adapt to old precompiled modules that used an earlier version of the API. We say "in theory"; because it is not used this way in practice.

[77]The head of this list is top_module. This is occasionally useful to know. The list is actually set up at runtime.

The only other entry is for handlers. We will look at this in more detail further on. Suffice it to say, for now, that this entry points to a list of strings and functions that define the relationship between MIME or handler types and the functions that handle them. All the other entries are defined to NULL, which simply means that the module does not use those particular hooks.

The equivalent structure in 2.0 looks like this:

static void register_hooks(apr_pool_t *p)
{
    ap_hook_handler(asis_handler,NULL,NULL,APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA asis_module =
{
    STANDARD20_MODULE_STUFF,
    NULL,			/* create per-directory config structure */
    NULL,			/* merge per-directory config structures */
    NULL,			/* create per-server config structure */
    NULL,			/* merge per-server config structures */
    NULL,			/* command apr_table_t */
    register_hooks			/* register hooks */
};

Note that we have to show the register_hooks( ) function to match the functionality of the 1.3 module structure. Once more, STANDARD20_MODULE_STUFF is required for all module structures, and the register_hooks( ) function replaces most of the rest of the old 1.3 structure. How this works is explained in detail in the next section.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.