Show Contents Previous Page Next Page Chapter 11 - C API Reference Guide, Part II In this section... Show Contents Go to Top Previous Page Next Page
The C-language API allows modules to install their own configuration directives. The directives' syntax and usage information are defined in a Whereas the configuration API is optional in Perl modules due to the catchall PerlSetVar directive, C-language programmers don't have this luxury. You'll have to create custom configuration directives in order to write any module that requires runtime configuration information. Show Contents Go to Top Previous Page Next PageModules are responsible for managing their own configuration data. There are two general types of configuration data: data that apply to a particular server or virtual host and data that apply to a directory or URI. A module can maintain both server-specific and directory-specific configuration information or just one or the other, depending on its needs. Because there may be dozens of virtual hosts and hundreds of directories, the Apache API allows modules to juggle thousands of configuration records. During configuration file processing, Apache will call your module's configuration allocation and processing routines at the right time and in the right order to create the configuration data. Then, at request time, Apache will choose the correct configuration record to return to your handler when the handler requests it.
The work of creating and maintaining configuration records is done in several steps. In the first step, the module is given an opportunity to allocate storage for its private configuration settings and to create a reasonable set of defaults, if it chooses. The content of the configuration data is entirely private to your module. Apache sees it only as an opaque During the second step, which occurs during configuration file processing, the module's directives are parsed and passed back to your code for processing, along with the initialized configuration settings from the previous phase. There is one directive handler for each custom directive that your module declares. The directive handler will alter the configuration block in some way to record the meaning of the directive. Typically the handler will change the contents of a field or add an entry to a table.
The third step is the mysterious-sounding "merging" process. The idea is that configuration information is often nested. For example, a particular directive could appear in the main part of the configuration file, in a <VirtualHost> section, in a <Directory> section, and in a The last step actually occurs during the transaction. Handlers that need access to their module's per-server or per-directory configuration settings request it from Apache. The ap_get_module_config() API function is able to perform a quick, one-step lookup of your module's configuration data relevant to the current transaction, no matter how many configuration blocks were constructed during server startup. Creating and Merging Configuration Data Blocks Show Contents Go to Top Previous Page Next Page
Your module declares its intent to maintain configuration information by filling in one or more of the slots in the 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)
The create_server_config() function is an opportunity for the module to allocate per-server configuration data. It is passed a resource pool and a create_dir_config() is similar, except that it is called to create per-directory configuration information (directives contained within <Directory>, <Location>, or As a concrete example, consider a "traffic cop" module that regulates the flow of traffic on a server. It has two configuration settings: one which sets the maximum speed limit on the server (in bits per second, say) and one which contains a list of domains that have "right-of-way" through the server and can fetch documents at a higher maximum speed. This module could store the information in the following per-server configuration record: typedef struct { int speed_limit; table *right_of_way; } traffic_server_config;
The following definition of traffic_create_server_config() allocates the storage for the per-server configuration information and sets up appropriate defaults. static void *traffic_create_server_config (pool *p, server_rec *s) { traffic_server_config *cfg = (traffic_server_config *)ap_pcalloc(p, sizeof(traffic_server_config)); cfg->speed_limit = 55; cfg->right_of_way = ap_make_table(p, 0); return (void *)cfg; }
This initial data block will be passed back to your module's directive handlers as a
A create_dir_config() routine will look almost identical to this, but instead of receiving a
Later on in the process, Apache may be called upon to process a directive that needs to be merged into the parent configuration. You can define up to two such merge routines. The merge_server_config() routine is called at server startup time to merge directives in <VirtualHost> blocks with the configuration for the parent server. It receives a pointer to a resource pool, a pointer to the parent server configuration, and a pointer to the child server configuration. The merge routine's job is to create a new configuration structure that combines the two and to return it to Apache as a merge_dir_config() is similar, but it happens at request time and operates on two per-directory structures: the parent directory's configuration and the current directory's configuration. It is expected to merge the two and return a new per-directory configuration structure that combines the configurations in some sensible way. For example, here is a plausible server merge routine for the traffic cop
configuration. We want to overwrite the static void *traffic_merge_server_config (pool *p, void* base, void* new) { traffic_server_config *merged = (traffic_server_config*)ap_pcalloc(p, sizeof(traffic_server_config)); traffic_server_config *parent = (traffic_server_config*)base; traffic_server_config *child = (traffic_server_config*)new; merged->speed_limit = child->speed_limit ? child->speed_limit : parent->speed_limit; merged->right_of_way = ap_overlay_tables(p, parent->right_of_way, child->right_of_way); return (void*)merged; } If your module does not define any merge routines, then Apache will use the configuration of the most recent server or directory configuration, ignoring any directives which previously have been defined for a block's ancestors. If your module defines no create_server_config() or create_dir_config() routine, then it will have no runtime configuration blocks. However, this doesn't mean that the module can't maintain any configuration information at all; it can still maintain some state in static variables. However, this information will be global to the module, rather than server-specific or directory-specific. This rarely works out the way you want it, nor is it thread-safe.
Rather than having the create_server_config() and create_dir_config() fill in the configuration records' fields with default values, it is often useful to have the two routines fill in the configuration fields with explicit merged->attr = base->attr == UNSET ? base->attr : new->attr;
There is one major trap in the current Apache configuration API. If your module depends on per-server records and <VirtualHost> sections are in use, then at least one of your module's configuration directives must be present in the <VirtualHost> section or your module's create_server_config() routine will never be called. As a result, your module will have no chance to create its per-server configuration before its handlers are called at transaction time. There are two ways around this problem. You can simply DECLINE to handle the transaction if the per-server configuration block is Copyright © 1999 by O'Reilly & Associates, Inc. |