Would there be any interest in including example modules with the Apache
source distribution? And/or could a complete example module be included
in the documentation for developers? (Personally I'd prefer it be
included in the source distribution...The web documentation has become
quite out of date in places and it's more likely to be current if it
could be included in the distribution test suite.)
Yesterday, in trying to convey how to implement a module, I developed a
"hello world" example module that has a "handler" hook that responds
with a canned message to all requests. (It demonstrates hooks, and I
have a slightly more complex example showing how to read per-directory
configurations.)
I would have found a barebones example immensely useful and would have
saved me much time and code-grepping.
Anyways, I've attached my "hello world" module. Please
comment/correct/chastise as you see fit, I am by no means an expert. ;^>
/* mod_hello_world.c
* Written by Chris Knight, NASA Ames Research Center
* [EMAIL PROTECTED]
*
* Build using:
* $APACHE_HOME/build/libtool gcc -c -I$APACHE_HOME/include mod_hello_world.c
*
* followed by:
* $APACHE_HOME/build/libtool --mode=link $(CC) -o $@ -fPIC $(INCLUDE) \
*hello_world.lo $(LIBS) $(APACHE_CFLAGS) -rpath /usr/lib -avoid-version
*/
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "ap_config.h"
#include "http_log.h"
// Forward declaration of the module, see the bottom of this document for
// details.
module AP_MODULE_DECLARE_DATA hello_world_module;
// A struct to hold this module's configuration parameters.
typedef struct conf {
apr_pool_t *p;
char *message;
} conf;
/**
* Instantiate this module's configuration structure.
* This function is called by Apache for each configuration section and is
* passed by Apache to other module functions.
* @param p The memory pool to be used by this module.
* @param d The directory/location for this section?
* @return The configuration block's pointer.
*/
static void *create_conf(apr_pool_t *p, char *d) {
conf *c = apr_pcalloc(p, sizeof(conf));
c->p = p;
c->message = NULL;
return c;
}
/**
* Set the message in this module's configuration. This is called when
* the HelloWorldMsg directive is encountered in a configuration section.
* @param cmd The directive parameters ???
* @param config The section's configuration
* @param arg1 The message.
* @return The error message if there is an error with this directive.
*/
static const char *set_message(cmd_parms *cmd, void *config, const char *arg1) {
conf *c = (conf *)config;
c->message = (char *)apr_pstrdup(c->p, arg1);
return NULL;
}
/**
* Provide the response to the request.
* @param r The request record. (Containing all of the details of the request.)
* @return Flag indicating successful handling of the request.
*/
int handle(request_rec *r) {
conf *conf = ap_get_module_config(r->per_dir_config, &hello_world_module);
// if there is no message declared for this URI (no matching ,
// , etc) then let another hook handle the request.
if (conf == NULL || conf->message == NULL) return DECLINED;
// otherwise, send our message to the client
ap_rprintf(r, conf->message);
// and tell Apache that we've handled the request
return OK;
}
/**
* Connect hook functions to Apache so that Apache will call them at the
* appropriate time.
* @param p The memory pool to use.
*/
static void register_hooks(apr_pool_t *p) {
// The handler hooks are used to provide the response's contents for a
// successful request.
ap_hook_handler(handle, NULL, NULL, APR_HOOK_MIDDLE);
}
// This list details which configuration directives this module understands.
static const command_rec cmds[] = {
// The HelloWorldMsg directive takes one argument, the message to send.
AP_INIT_TAKE1("HelloWorldMsg", set_message, NULL, OR_AUTHCFG,
"specify the message to send clients"),
// Indicates the end of the list of directives.
{NULL}
};
// This module declaration tells Apache which configuration directives this
// module understands and which methods to call to connect the hook functions.
module AP_MODULE_DECLARE_DATA hello_world_module = {
STANDARD20_MODULE_STUFF, // always need this
create_conf, // called for each configuration section
NULL,// called for nested configuration sections (?)
NULL,// called once per server configuration
NULL,// ?
cmds,// which configuration directives do I handle?
register_hooks // function to be called at bind-time
};