Show Contents Previous Page Next Page Chapter 11 - C API Reference Guide, Part II / Implementing Configuration Directives in C To show you how custom configuration directives work in practice, let's go ahead and add a directive handler table to the mod_hello example that we introduced long, long ago in Chapter 2, A First Module. We start simply by adding the ability for users to configure mod_hello to say hello to something other than "world," which you are surely tired of by now. Once we are done making the required modifications to mod_hello.c, the message "Hello world" can be changed to "Hello Dolly" by adding this line to any configuration file: HelloTo Dolly The complete source code for the modified mod_hello.c is shown in Example 11-3.
The first change over the original version is to declare the module hello_module;
Next, we declare a new data type to hold our per-directory configuration data, typedef struct {
char *to;
} hello_dir_config;
Now we need to add a function to create a new per-directory structure. This will be called each time Apache notices one of the module's directives in a directory or location configuration section. Our function simply allocates a new static void *hello_create_dir_config(pool *p, char *path)
{
hello_dir_config *cfg =
(hello_dir_config *)ap_pcalloc(p, sizeof(hello_dir_config));
cfg->to = "world";
return (void *)cfg;
}
Now we must modify the hello_create_dir_config, /* per-directory config creator */ In this case, our configuration data is so simple that there's no need to write a directory config merge function. In the absence of a merge function, Apache will use the most specific configuration record, giving us the most recent value of Hello-To. This is exactly what we want.
What's next? We need a function to actually handle the directive. Once Apache hits the HelloTo directive, it will call this function, passing it a static const char *hello_cmd_to(cmd_parms *parms,
void *mconfig, char *to)
{
hello_dir_config *cfg = (hello_dir_config *)mconfig;
cfg->to = (char*)ap_pstrdup(parms->pool, to);
return NULL;
}
In order for Apache to know about our new directive, we need to create a static command_rec hello_cmds[] =
{
{
"HelloTo", /* directive name */
hello_cmd_to, /* config action routine */
NULL, /* argument to include in call */
OR_ALL, /* where available */
TAKE1, /* arguments */
"Who we say hello to, default is 'world'" /* description */
},
{NULL}
};
Notice that the
We can now add the module MODULE_VAR_EXPORT hello_module =
{
STANDARD_MODULE_STUFF,
NULL, /* module initializer */
hello_create_dir_config, /* per-directory config creator */
NULL, /* dir config merger */
NULL, /* server config creator */
NULL, /* server config merger */
hello_cmds, /* command table */
hello_handlers, /* [9] content handlers */
NULL, /* [2] URI-to-filename translation */
NULL, /* [5] check/validate user_id */
NULL, /* [6] check user_id is valid *here* */
NULL, /* [4] check access by host address */
NULL, /* [7] MIME type checker/setter */
NULL, /* [8] fixups */
NULL, /* [10] logger */
NULL, /* [3] header parser */
NULL, /* process initialization */
NULL, /* process exit/cleanup */
NULL /* [1] post read_request handling */
};
The last thing we need to do is to actually put the configuration data to use. In the content handler function hello_handler(), we add the following line to retrieve the configuration structure: hello_dir_config *cfg = (hello_dir_config *)
ap_get_module_config(r->per_dir_config, &hello_module);
Now we change the call to rputs(), where we used to print out "Hello world", into a call to rprintf() that uses the configuration information to print out a customized message: rprintf(r, "say \"hello %s\"?\n", cfg->to); Recompile the module, restart the server, and start saying "Hello" to whomever you choose! Example 11-3. mod_hello with a Custom Configuration Directive /* file: mod_hello.c */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_protocol.h" /* Forward declaration so that ap_get_module_config() can find us. */ module hello_module; /* Here's our per-directory configuration data */
typedef struct {
char *to;
} hello_dir_config;
/* This function is called to create the default per-directory
configuration */
static void *hello_create_dir_config(pool *p, char *path)
{
hello_dir_config *cfg =
(hello_dir_config *)ap_pcalloc(p, sizeof(hello_dir_config));
cfg->to = "world";
return (void *)cfg;
}
/* This is the handler for the HelloTo directive */ static const char *hello_cmd_to(cmd_parms *parms, void *mconfig, char *to) {
hello_dir_config *cfg = (hello_dir_config *)mconfig;
cfg->to = (char *)ap_pstrdup(parms->pool, to);
return NULL;
}
/* Make the name of the content handler known to Apache */
static command_rec hello_cmds[] =
{
{
"HelloTo", /* directive name */
hello_cmd_to, /* config action routine */
NULL, /* argument to include in call */
OR_ALL, /* where available */
TAKE1, /* arguments */
"Who we say hello to, default is 'world'" /* description */
},
{NULL}
};
/* here's the content handler */
static int hello_handler(request_rec *r) {
const char* hostname;
hello_dir_config *cfg;
r->content_type = "text/html";
ap_send_http_header(r);
hostname = ap_get_remote_host(r->connection,
r->per_dir_config, REMOTE_NAME);
cfg = (hello_dir_config *)
ap_get_module_config(r->per_dir_config, &hello_module);
ap_rputs("<HTML>\n", r);
ap_rputs("<HEAD>\n", r);
ap_rputs("<TITLE>Hello There</TITLE>\n", r);
ap_rputs("</HEAD>\n", r);
ap_rputs("<BODY>\n", r);
ap_rprintf(r, "<H1>Hello %s</H1>\n", hostname);
ap_rputs("Here we go again...", r);
ap_rprintf(r, "\"Hello %s\"!\n", cfg->to);
ap_rputs("</BODY>\n", r);
ap_rputs("</HTML>\n", r);
return OK; } /* Make the name of the content handler known to Apache */
static handler_rec hello_handlers[] =
{
{"hello-handler", hello_handler},
{NULL}
};
/* Tell Apache what phases of the transaction we handle */
module MODULE_VAR_EXPORT hello_module =
{
STANDARD_MODULE_STUFF,
NULL, /* module initializer */
hello_create_dir_config, /* per-directory config creator */
NULL, /* dir config merger */
NULL, /* server config creator */
NULL, /* server config merger */
hello_cmds, /* command table */
hello_handlers, /* [9] content handlers */
NULL, /* [2] URI-to-filename translation */
NULL, /* [5] check/validate user_id */
NULL, /* [6] check user_id is valid *here* */
NULL, /* [4] check access by host address */
NULL, /* [7] MIME type checker/setter */
NULL, /* [8] fixups */
NULL, /* [10] logger */
NULL, /* [3] header parser */
NULL, /* process initialization */
NULL, /* process exit/cleanup */
NULL /* [1] post read_request handling */
};
Show Contents Previous Page Next PageCopyright © 1999 by O'Reilly & Associates, Inc. |
HIVE: All information for read only. Please respect copyright! |