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 10 - C API Reference Guide, Part I / Major Data Structures / The module Record
Handler and callback slots

The rest of the module structure is mostly function pointers. Each field holds the address of a routine to invoke during the server's various initialization, transaction, and cleanup phases, or NULL if there is no routine to call. Because the Apache API was developed over time, the order of handlers in the module table does not correspond to the order in which they are called during the request cycle. We will describe them in the order in which they appear in the data structure. See Chapter 3, The Apache Module Architecture and API, for the correct chronological perspective.

Module initialization handler

void module_init(server_rec *s, pool *p);

This handler is called during the module initialization phase immediately after the server is started. This is where modules initialize data, consult configuration files, or do other preparatory work in the parent server before any children are forked off or threads spawned.

Under Unix and other process forking systems, each child process will inherit its own copy of any data structures created during this phase. Under threading systems, module authors will need to take care of maintaining per-thread instances of such data if needed.

The initialization function will be called with two arguments: a pointer to the current server_rec structure (described in detail below) and a pointer to a resource pool whose lifetime ends only when the server is finally shut down.

For an example of a module that steps in during this phase, see mod_mime, which builds its MIME types hash table from the mime.types file once during initialization.

Configuration creation and merging routines (four of them!)

void *create_dir_config (pool *p, char *dir)
void *merge_dir_config (pool *p, void *base_conf, void *new_conf)
void *create_server_config (pool *p, server_rec *s)
void *merge_server_config (pool *p, void *base_conf, void *new_conf)

Modules may add their own configuration directives to the server, which will then act just like built-in configuration directives. However, the server core knows nothing about what to do with these directives, and instead passes back the preparsed directives to the module for processing.

These four slots contain pointers to optional routines for handling module-specific configuration data blocks. You are not obliged to fill in all of them, or indeed any at all. See "Implementing Configuration Directives in C" in Chapter 11, C API Reference Guide, Part II, for details.

Configuration directive (command) table

command_rec *cmds

The command_table field holds a pointer to a command_rec structure, which describes each of the module's configuration directives in detail and points back to configuration callbacks to process the directives.

The command_rec structure is described in detail in Chapter 11 under "Implementing Configuration Directives in C."

Response handlers table

handler_rec *handlers

The next field contains the module dispatch table for the response phase of the request. It can be used to map one or more MIME content types to content handlers defined within the module or to map symbolic handler names to handler functions.

Here is a slightly expanded version of our Chapter 2mod_hello example:

static handler_rec hello_handlers[] =
   {"hello-handler", hello_handler},
   {"application/x-hello", hello_handler},

The handler table is an array of handler_rec structures. The last entry in the array must be a NULL record. Each handler_rec entry in the array has the following simple structure:

char *content_type

The first element is the content type or the symbolic handler name. As described in the introduction to Chapter 4, Content Handlers, Apache will dispatch on the handler name or the MIME type, depending on the current directory's configuration. In this example, the hello_handler() content-handling subroutine is associated both with the symbolic handler name hello-handler and a magic MIME type of application/x-hello. This means that you can arrange for the content handler to be invoked either by setting the handler explicitly in a <Directory> or <Location> block with SetHandler hello-handler, or by setting the handler implicitly by requesting a document of MIME type application/x-hello (since there is no default MIME file extension mapping for this type of document, you'll have to make one up using AddType).

It is perfectly valid for several modules to register their interest in handling the same MIME type. Apache will call them from most recent to least recent until one returns a status code other than DECLINED. It is also possible to use wildcards in the MIME type. For example, the http_core default handler registers */*, indicating that it will handle a request of any type that is not handled by a more specific module.

int handler(request_rec *r)

This is a pointer to the content handler subroutine that will be invoked to process the request at response time. As with the other HTTP request time callbacks, the function is passed a request_rec * structure and is expected to return an integer status value. The list of symbolic status code constants can be found in the header file httpd.h. The constants are identical to the list given in Table 3-1.

The content handler is something of an oddball among the various handlers because it is registered indirectly through the handler_rec. This structure allows modules to register multiple handlers for the response phase, leaving Apache to select one of them based on the content_type for a given request. As we are about to see, handlers for the other phases are plugged directly into the module record.

URI translation handler

int translate_handler(request_rec *r)

This is the slot where a pointer to the URI translation handler, if any, is plugged in. It receives an argument consisting of a request_rec pointer and is expected to return an integer status code. Unless explicitly stated otherwise, the other phase handlers have similar calling conventions.

Authentication handler

int check_user_id(request_rec *r)

This is the slot where a pointer to the authentication handler, if any, is registered.

Authorization handler

int auth_checker(request_rec *r)

This is the slot where the authorization handler subroutine, if any, is registered.

Access handler

int access_checker(request_rec *r)

This is the slot where the access control handler subroutine, if any, is registered.

MIME type handler

int type_checker(request_rec *r)

This is the slot where the MIME type checker subroutine, if any, is registered.

Fixup handler

int fixer_upper(request_rec *r)

This is the slot where the fixup handler, if any, is registered.

Logging handler

int logger(request_rec *r)

This is the slot where the logging handler, if any, is registered.

Header parser handler

int header_parser(request_rec *r)

This is the slot where the header parser handler subroutine, if any, is registered.

Child initialization handler

void child_init(server_rec *s, pool *p)

This is where the child initialization subroutine is registered. Unlike other handlers, this subroutine is not called with a request record (there is no request at this stage). Instead, it is called with two arguments consisting of a server_rec pointer and a resource pool. It can do any processing or initialization it needs. If the routine needs to allocate some private storage, it can allocate memory from the resource pool and store a pointer to the returned structure in a static variable. The memory contained in the pool will not be released until the child process exits.

The child_init function should return no result.

Child exit handler

void child_exit(server_rec *r, pool *p)

This is the slot where the child exit handler is called. The exit handler should undo everything that the child init handler did. The handler is called with a server_rec pointer and a resource pool and should return no function result.

Post read request handler

int post_read_request(request_rec *r)

This is the slot where the post read request handler subroutine, if any, is registered.

   Show Contents   Previous Page   Next Page
Copyright 1999 by O'Reilly & Associates, Inc.