Optional Hook Example

Here’s a complete example of an optional hook (with comments following after the lines to which they refer). This can be found in .../modules/experimental. It comprises three files, mod_optional_hook_export.h, mod_optional_hook_export.c, and mod_optional_hook_import.c. What it actually does is call the hook, at logging time, with the request string as an argument.

First we start with the header, mod_optional_hook_export.h.

#include "ap_config.h"

This header declares the various macros needed for hooks.

AP_DECLARE_HOOK(int,optional_hook_test,(const char *))

Declare the optional hook (i.e., a function that looks like int optional_hook_test(const char *)). And that’s all that’s needed in the header.

Next is the implementation file, mod_optional_hook_export.c.

#include "httpd.h"
#include "http_config.h"
#include "mod_optional_hook_export.h"
#include "http_protocol.h"

Start with the standard includes — but we also include our own declaration header (although this is always a good idea, in this case it is a requirement, or other things won’t work).

AP_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(int,optional_hook_test,(const char *szStr),
                                   (szStr),OK,DECLINED)

Then we go to the implementation of the optional hook — in this case it makes sense to call all the hooked functions, since the hook we are implementing is essentially a logging hook. We could have declared it void, but even logging can go wrong, so we give the opportunity to say so.

static int ExportLogTransaction(request_rec *r)
{
    return ap_run_optional_hook_test(r->the_request);
}

This is the function that will actually run the hook implementation, passing the request string as its argument.

static void ExportRegisterHooks(apr_pool_t *p)
{
    ap_hook_log_transaction(ExportLogTransaction,NULL,NULL,APR_HOOK_MIDDLE);
}

Here we hook the log_transaction hook to get hold of the request string in the logging phase (this is, of course, an example of the use of a standard hook).

module optional_hook_export_module =
{
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    ExportRegisterHooks
};

Finally, the module structure — the only thing we do in this module structure is to add hook registration.

Finally, an example module that uses the optional hook, optional_hook_import.c.

#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "mod_optional_hook_export.h"

Again, the standard stuff, but also the optional hooks declaration (note that you always have to have the code available for the optional hook, or at least its header, to build with).

static int ImportOptionalHookTestHook(const char *szStr)
{
    ap_log_error(APLOG_MARK,APLOG_ERR,OK,NULL,"Optional hook test said: %s",
                 szStr);

    return OK;
}

This is the function that gets called by the hook. Since this is just a test, we simply log whatever we’re given. If optional_hook_export.c isn’t linked in, then we’ll log nothing, of course.

static void ImportRegisterHooks(apr_pool_t *p)
{
    AP_OPTIONAL_HOOK(optional_hook_test,ImportOptionalHookTestHook,NULL,
                     NULL,APR_HOOK_MIDDLE);
}

Here’s where we register our function with the optional hook.

module optional_hook_import_module=
{
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    ImportRegisterHooks
};

And finally, the module structure, once more with only the hook registration function in it.