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 Page Copyright © 1999 by O'Reilly & Associates, Inc. |