mirror of
https://github.com/apache/httpd.git
synced 2025-05-17 15:21:13 +03:00
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87119 13f79535-47bb-0310-9956-ffa450edef68
208 lines
6.0 KiB
HTML
208 lines
6.0 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
<html>
|
|
<head>
|
|
<title>Apache 2.0 Hook Functions</title>
|
|
</head>
|
|
|
|
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
|
|
<BODY
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#000080"
|
|
ALINK="#FF0000"
|
|
>
|
|
|
|
<!--#include virtual="header.html" -->
|
|
|
|
<H1 align="center">Apache Hook Functions</H1>
|
|
|
|
<P>In general, a hook function is one that Apache will call at some
|
|
point during the processing of a request. Modules can provide
|
|
functions that are called, and specify when they get called in
|
|
comparison to other modules.</P>
|
|
|
|
<H2>Creating a hook function</H2>
|
|
|
|
<P>In order to create a new hook, four things need to be done:</P>
|
|
|
|
<H3>Declare the hook function</H3>
|
|
|
|
<P>Use the DECLARE_HOOK macro, which needs to be given the name of the
|
|
hook, the return type of the hook function and the arguments. For
|
|
example, if the hook returns an <TT>int</TT> and takes a
|
|
<TT>request_rec *</TT> and an <TT>int</TT> and is called
|
|
"do_something", then declare it like this:</P>
|
|
|
|
<TT>DECLARE_HOOK(int,do_something,(request_rec *r,int n))</TT>
|
|
|
|
<P>This should go in a header which modules will include if they want
|
|
to use the hook.</P>
|
|
|
|
<H3>Create the hook structure</H3>
|
|
|
|
<P>Each source file that exports a hook has a private structure which
|
|
is used to record the module functions that use the hook. This is
|
|
declared as follows:</P>
|
|
|
|
<PRE>
|
|
HOOK_STRUCT(
|
|
HOOK_LINK(do_something)
|
|
...
|
|
)
|
|
</PRE>
|
|
|
|
<H3>Implement the hook caller</H3>
|
|
|
|
<P>The source file that exports the hook has to implement a function
|
|
that will call the hook. There are currently three possible ways to do
|
|
this. In all cases, the calling function is called
|
|
<TT>ap_run_<I>hookname</I>()</TT>.</P>
|
|
|
|
<H4>Void hooks</H4>
|
|
|
|
<P>If the return value of a hook is <TT>void</TT>, then all the hooks are
|
|
called, and the caller is implemented like this:</P>
|
|
|
|
<TT>IMPLEMENT_HOOK_VOID(do_something,(request_rec *r,int
|
|
n),(r,n))</TT>
|
|
|
|
<P>The second and third arguments are the dummy argument declaration and
|
|
the dummy arguments as they will be used when calling the hook. In
|
|
other words, this macro expands to something like this:</P>
|
|
|
|
<PRE>
|
|
void ap_run_do_something(request_rec *r,int n)
|
|
{
|
|
...
|
|
do_something(r,n);
|
|
}
|
|
</PRE>
|
|
|
|
<H4>Hooks that return a value</H4>
|
|
|
|
<P>If the hook returns a value, then it can either be run until the first
|
|
hook that does something interesting, like so:</P>
|
|
|
|
<TT>IMPLEMENT_HOOK_RUN_FIRST(int,do_something,(request_rec *r,int n),(r,n),DECLINED)</TT>
|
|
|
|
<P>The first hook that <I>doesn't</I> return <TT>DECLINED</TT> stops
|
|
the loop and its return value is returned from the hook caller. Note
|
|
that <TT>DECLINED</TT> is the tradition Apache hook return meaning "I
|
|
didn't do anything", but it can be whatever suits you.</P>
|
|
|
|
<P>Alternatively, all hooks can be run until an error occurs. This
|
|
boils down to permitting <I>two</I> return values, one of which means
|
|
"I did something, and it was OK" and the other meaning "I did
|
|
nothing". The first function that returns a value other than one of
|
|
those two stops the loop, and its return is the return value. Declare
|
|
these like so:</P>
|
|
|
|
<TT>IMPLEMENT_HOOK_RUN_ALL(int,do_something,(request_rec *r,int
|
|
n),(r,n),OK,DECLINED)</TT>
|
|
|
|
<P>Again, <TT>OK</TT> and <TT>DECLINED</TT> are the traditional
|
|
values. You can use what you want.</P>
|
|
|
|
<H3>Call the hook callers</H3>
|
|
|
|
<P>At appropriate moments in the code, call the hook caller, like
|
|
so:</P>
|
|
|
|
<PRE>
|
|
int n,ret;
|
|
request_rec *r;
|
|
|
|
ret=ap_run_do_something(r,n);
|
|
</PRE>
|
|
|
|
<H2>Hooking the hook</H2>
|
|
|
|
<P>A module that wants a hook to be called needs to do two
|
|
things.</P>
|
|
|
|
<H3>Implement the hook function</H3>
|
|
|
|
<P>Include the appropriate header, and define a static function of the
|
|
correct type:</P>
|
|
|
|
<PRE>
|
|
static int my_something_doer(request_rec *r,int n)
|
|
{
|
|
...
|
|
return OK;
|
|
}
|
|
</PRE>
|
|
|
|
<H3>Add a hook registering function</H3>
|
|
|
|
<P>During initialisation, Apache will call each modules hook
|
|
registering function, which is included in the module structure:</P>
|
|
|
|
<PRE>
|
|
static void my_register_hooks()
|
|
{
|
|
ap_hook_do_something(my_something_doer,NULL,NULL,HOOK_MIDDLE);
|
|
}
|
|
|
|
mode MODULE_VAR_EXPORT my_module =
|
|
{
|
|
...
|
|
my_register_hooks /* register hooks */
|
|
};
|
|
</PRE>
|
|
|
|
<H3>Controlling hook calling order</H3>
|
|
|
|
<P>In the example above, we didn't use the three arguments in the hook
|
|
registration function that control calling order. There are two
|
|
mechanisms for doing this. The first, rather crude, method, allows us
|
|
to specify roughly where the hook is run relative to other
|
|
modules. The final argument control this. There are three possible
|
|
values:</P>
|
|
|
|
<PRE>
|
|
HOOK_FIRST
|
|
HOOK_MIDDLE
|
|
HOOK_LAST
|
|
</PRE>
|
|
|
|
<P>All modules using any particular value may be run in any order
|
|
relative to each other, but, of course, all modules using
|
|
<TT>HOOK_FIRST</TT> will be run before <TT>HOOK_MIDDLE</TT> which are
|
|
before <TT>HOOK_LAST</TT>. Modules that don't care when they are run
|
|
should use <TT>HOOK_MIDDLE</TT>. <I>(I spaced these out so people
|
|
could do stuff like <TT>HOOK_FIRST-2</TT> to get in slightly earlier,
|
|
but is this wise? - Ben)</I></P>
|
|
|
|
<P>Note that there are two more values, <TT>HOOK_REALLY_FIRST</TT> and
|
|
<TT>HOOK_REALLY_LAST</TT>. These should only be used by the hook
|
|
exporter.</P>
|
|
|
|
<P>The other method allows finer control. When a module knows that it
|
|
must be run before (or after) some other modules, it can specify them
|
|
by name. The second (third) argument is a NULL-terminated array of
|
|
strings consisting of the names of modules that must be run before
|
|
(after) the current module. For example, suppose we want "mod_xyz.c"
|
|
and "mod_abc.c" to run before we do, then we'd hook as follows:</P>
|
|
|
|
<PRE>
|
|
static void register_hooks()
|
|
{
|
|
static const char * const aszPre[]={ "mod_xyz.c", "mod_abc.c", NULL };
|
|
|
|
ap_hook_do_something(my_something_doer,aszPre,NULL,HOOK_MIDDLE);
|
|
}
|
|
</PRE>
|
|
|
|
<P>Note that the sort used to achieve this is stable, so ordering set
|
|
by <TT>HOOK_<I>ORDER</I></TT> is preserved, as far as is
|
|
possible.</P>
|
|
|
|
<I>Ben Laurie, 15th August 1999</I>
|
|
|
|
<!--#include virtual="footer.html" -->
|
|
|
|
</body>
|
|
</html>
|