Since
a single instance of Apache may be called on to handle a request for
any of the configured virtual hosts (or the main host), a structure
is defined that holds the information related to each host. This
structure, server_rec
, is defined in
include/httpd.h:
struct server_rec { /** The process this server is running in */ process_rec *process; /** The next server in the list */ server_rec *next; /** The name of the server */ const char *defn_name; /** The line of the config file that the server was defined on */ unsigned defn_line_number; /* Contact information */ /** The admin's contact information */ char *server_admin; /** The server hostname */ char *server_hostname; /** for redirects, etc. */ apr_port_t port; /* Log files --- note that transfer log is now in the modules... */ /** The name of the error log */ char *error_fname; /** A file descriptor that references the error log */ apr_file_t *error_log; /** The log level for this server */ int loglevel; /* Module-specific configuration for server, and defaults... */ /** true if this is the virtual server */ int is_virtual; /** Config vector containing pointers to modules' per-server config * structures. */ struct ap_conf_vector_t *module_config; /** MIME type info, etc., before we start checking per-directory info */ struct ap_conf_vector_t *lookup_defaults; /* Transaction handling */ /** I haven't got a clue */ server_addr_rec *addrs; /** Timeout, in seconds, before we give up */ int timeout; /** Seconds we'll wait for another request */ int keep_alive_timeout; /** Maximum requests per connection */ int keep_alive_max; /** Use persistent connections? */ int keep_alive; /** Pathname for ServerPath */ const char *path; /** Length of path */ int pathlen; /** Normal names for ServerAlias servers */ apr_array_header_t *names; /** Wildcarded names for ServerAlias servers */ apr_array_header_t *wild_names; /** limit on size of the HTTP request line */ int limit_req_line; /** limit on size of any request header field */ int limit_req_fieldsize; /** limit on number of request header fields */ int limit_req_fields; };
Most of this structure is used by the Apache core, but each module
can also have a per-server configuration, which is accessed via the
module_config
member, using
ap_get_module_config()
. Each module creates this
per-module configuration structure itself, so it has complete control
over its size and contents. This can be seen in action in the case
filter example that follows. Here are excerpts from
modules/experimental/mod_case_filter.c showing
how it is used:
typedef struct { int bEnabled; } CaseFilterConfig;
Here we define a structure to hold the per-server configuration. Obviously, a module can put whatever it likes in this structure:
static void *CaseFilterCreateServerConfig(apr_pool_t *p,server_rec *s) { CaseFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig); pConfig->bEnabled=0; return pConfig; }
This function is linked in the module structure (see later) in the
create_server_config
slot. It is called once for
each server (i.e., a virtual host or main host) by the core. The
function must allocate the storage for the per-server configuration
and initialize it. (Note that because apr_pcalloc(
)
zero-fills the memory it allocates,
there’s no need to actually initialize the
structure, but it is done for the purpose of clarity.) The return
value must be the per-server configuration structure:
static const char *CaseFilterEnable(cmd_parms *cmd, void *dummy, int arg) { CaseFilterConfig *pConfig=ap_get_module_config(cmd->server->module_config, &case_filter_module); pConfig->bEnabled=arg; return NULL; }
This function sets the flag in the per-server configuration
structure, having first retrieved it using
ap_get_module_config()
. Note that you have to
pass the right thing as the first argument, i.e., the
module_config
element of the server structure. The
second argument is the address of the module’s
module structure, which is used to work out which configuration to
retrieve. Note that per-directory configuration is done differently:
static const command_rec CaseFilterCmds[] = { AP_INIT_FLAG("CaseFilter", CaseFilterEnable, NULL, RSRC_CONF, "Run a case filter on this host"), { NULL } };
This command invokes the function CaseFilterEnable(
)
. The RSRC_CONF
flag is what tells the
core that it is a per-server command (see the
include/httpd_config.h documentation for more
information).
To access the configuration at runtime, all that is needed is a pointer to the relevant server structure, as shown earlier. This can usually be obtained from the request, as seen in this example:
static void CaseFilterInsertFilter(request_rec *r) { CaseFilterConfig *pConfig=ap_get_module_config(r->server->module_config, &case_filter_module); if(!pConfig->bEnabled) return; ap_add_output_filter(s_szCaseFilterName,NULL,r,r->connection); }
One subtlety that isn’t needed by every module is configuration merging. This occurs when the main configuration has directives for a module, but so has the relevant virtual host section. Then the two are merged. The default way this is done is for the virtual host to simply override the main config, but it is possible to supply a merging function in the module structure. If you do, then the two configs are passed to it, and it creates a new config that is the two merged. How it does this is entirely up to you, but here’s an example from modules/metadata/mod_headers.c:
static void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv) { headers_conf *newconf = apr_pcalloc(p, sizeof(*newconf)); headers_conf *base = basev; headers_conf *overrides = overridesv; newconf->fixup_in = apr_array_append(p, base->fixup_in, overrides->fixup_in); newconf->fixup_out = apr_array_append(p, base->fixup_out, overrides->fixup_out); return newconf; }
In this case the merging is done by combining the two sets of configuration (which are stored in a standard APR array).